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

  Program:   Visualization Toolkit
  Module:    vtkAsynchronousBuffer.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
//#include <unistd.h>
#include "vtkAsynchronousBuffer.h"

//----------------------------------------------------------------------------
vtkAsynchronousBuffer::vtkAsynchronousBuffer()
{
  this->Blocking = 1;
  this->Threader = vtkMultiThreader::New();
  this->ThreadId = -1;
  this->Finished = 1;
  this->OutputConsumed = 1;
}

//----------------------------------------------------------------------------
vtkAsynchronousBuffer::~vtkAsynchronousBuffer()
{
  this->Threader->Delete();
  this->Threader = NULL;
}

//----------------------------------------------------------------------------
// the asynchrous update function
VTK_THREAD_RETURN_TYPE vtkAsynchronousBufferUpdate( void *arg )
{
  ThreadInfoStruct *info = (ThreadInfoStruct*)arg;
  vtkAsynchronousBuffer *self = (vtkAsynchronousBuffer*)(info->UserData);

  self->GetInput()->Update();
  self->Finished = 1;

  return VTK_THREAD_RETURN_VALUE;
}

//----------------------------------------------------------------------------
// Access to Finished should have a mutex lock around it.
void vtkAsynchronousBuffer::UpdateInformation()
{
  if (this->Blocking)
    {
    this->BlockingUpdateInformation();
    }
  else
    {
    this->NonblockingUpdateInformation();
    }
}

//----------------------------------------------------------------------------
// Access to Finished should have a mutex lock around it.
void vtkAsynchronousBuffer::NonblockingUpdateInformation()
{
  vtkDataSet *input = this->GetInput();
  vtkDataSet *output = this->GetOutput();
  unsigned long t1, t2;

  // just some error checking
  if (input == NULL)
    {
    vtkErrorMacro("No Input");
    return;
    }
  if (output == NULL)
    {
    vtkErrorMacro("No Output");
    return;
    }

  // Avoid accessing input if another thread is running.
  // I assume values from last UpdateInformation is sufficient.
  if ( ! this->Finished)
    {
    vtkDebugMacro("Still Updating");
    return;
    }

  // Test to see if we can promote data (copy form input to output)
  // If last promotion has not been consumed.
  // (The existance of a thread is used to detect promotable data.)
  if (this->OutputConsumed && this->ThreadId != -1)
    {
    // Promote the data (copy input to output)
    this->PromoteData();
    this->OutputConsumed = 0;
    // clean up thread.
    vtkDebugMacro("Promoting data to output");
    this->Threader->TerminateThread(this->ThreadId);
    this->ThreadId = -1;
    // This modified will cause update to be called ...
    // (not really necessary, because output has been modified by promotion).
    this->Modified();
    }

  // Test to see if we should start an asynchronous update.
  // Only start an update if we are not updating already,
  // and there is no promotable data.
  if (this->ThreadId == -1)
    {
    // check the update time of the input directly to pre determine
    // whether input will generate new data.
    input->UpdateInformation();
    if (input->GetPipelineMTime() > input->GetUpdateTime())
      {
      // spawn a thread and start an update.
      // what if an abort occurs?!! ...
      vtkDebugMacro("Spawn an update");
      this->Finished = 0;
      this->ThreadId =
	this->Threader->SpawnThread(vtkAsynchronousBufferUpdate, (void *)this);
      }
    }

  // Do the typical update information stuff (as if we were a simple source).
  output->SetLocality(0);
  t1 = this->GetMTime();
  t2 = output->GetMTime();
  if (t2 > t1)
    {
    t1 = t2;
    }
  output->SetPipelineMTime(t1);
  // Is it up to date? Really? Oh well.
  output->SetEstimatedWholeMemorySize(input->GetEstimatedWholeMemorySize());
  // Copy data specific information
  output->CopyInformation(input);
}

//----------------------------------------------------------------------------
// Access to Finished should have a mutex lock around it.
void vtkAsynchronousBuffer::BlockingUpdateInformation()
{
  vtkDataSet *input = this->GetInput();
  vtkDataSet *output = this->GetOutput();

  // just some error checking
  if (input == NULL)
    {
    vtkErrorMacro("No Input");
    return;
    }
  if (output == NULL)
    {
    vtkErrorMacro("No Output");
    return;
    }

  // make sure we are not already updating asynchronously.
  this->WaitForFinished();

  // Now we can look downstream for pipeline mtime.
  this->vtkSource::UpdateInformation();

  // Copy data specific information
  output->CopyInformation(input);
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::InternalUpdate(vtkDataObject *output)
{
  if (this->Blocking)
    {
    this->BlockingUpdate();
    }
  else
    {
    this->NonblockingUpdate();
    }
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::NonblockingUpdate()
{
  // Every thing has been done in UpdateInformation
  // Maybe we should leave the promotion to the update, but that might
  // cause a delay initiating the next asynchronous update.

  this->OutputConsumed = 1;
}

//----------------------------------------------------------------------------
// To make sure the data gets to output (for initialization)
// I am not positive this still works
void vtkAsynchronousBuffer::BlockingUpdate()
{
  if (this->GetInput() == NULL)
    {
    return;
    }

  // check to see if we are already updating (loop)
  if (this->Updating)
    {
    return;
    }

  // make sure we are not already updating asynchronously.
  this->WaitForFinished();

  // delete thread from last update (clean up)
  if (this->ThreadId != -1)
    {
    this->Threader->TerminateThread(this->ThreadId);
    this->ThreadId = -1;
    }

  // Do we need to update our input?
  if (this->GetInput()->GetUpdateTime() < this->GetInput()->GetPipelineMTime())
    {
    this->GetInput()->Update();
    }

  // This executes the copy if the input is more recent than the output
  this->PromoteData();
}

//----------------------------------------------------------------------------
// This may need a mutex lock.  I assume not because the spawned thread
// only set the variable to 1 at the end.  Any value of zero is ok,
// and any partial non zero value is ok too.
int vtkAsynchronousBuffer::TestForFinished()
{
  return (int)(this->Finished);
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::WaitForFinished()
{
  while ( ! this->Finished)
    {
    // vtkTimerLog::Sleep(10);
    }
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::PromoteData()
{
  if ( this->StartMethod )
    {
    (*this->StartMethod)(this->StartMethodArg);
    }
  this->Progress = 0.0;
  this->GetOutput()->Initialize(); //clear output
  this->Execute();
  if ( !this->AbortExecute )
    {
    this->UpdateProgress(1.0);
    }
  if ( this->EndMethod )
    {
    (*this->EndMethod)(this->EndMethodArg);
    }

  if ( this->GetInput()->ShouldIReleaseData() )
    {
    this->GetInput()->ReleaseData();
    }
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::Execute()
{
  this->GetOutput()->CopyStructure((vtkDataSet *)this->GetInput());

  this->GetOutput()->GetPointData()->PassData(
                 ((vtkDataSet *)this->GetInput())->GetPointData());
  this->GetOutput()->GetCellData()->PassData(
                 ((vtkDataSet *)this->GetInput())->GetCellData());
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataSetFilter::PrintSelf(os,indent);

  if (this->Blocking)
    {
    os << indent << "BlockingOn\n";
    }
  else
    {
    os << indent << "BlockingOff\n";
    }
  os << "Finished: " << this->Finished << endl;

  os << indent << "ThreadId: " << this->ThreadId << "\n";
}

<commit_msg>*** empty log message ***<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkAsynchronousBuffer.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
//#include <unistd.h>
#include "vtkAsynchronousBuffer.h"
#include "vtkDataInformation.h"

//----------------------------------------------------------------------------
vtkAsynchronousBuffer::vtkAsynchronousBuffer()
{
  this->Blocking = 1;
  this->Threader = vtkMultiThreader::New();
  this->ThreadId = -1;
  this->Finished = 1;
  this->OutputConsumed = 1;
}

//----------------------------------------------------------------------------
vtkAsynchronousBuffer::~vtkAsynchronousBuffer()
{
  this->Threader->Delete();
  this->Threader = NULL;
}

//----------------------------------------------------------------------------
// the asynchrous update function
VTK_THREAD_RETURN_TYPE vtkAsynchronousBufferUpdate( void *arg )
{
  ThreadInfoStruct *info = (ThreadInfoStruct*)arg;
  vtkAsynchronousBuffer *self = (vtkAsynchronousBuffer*)(info->UserData);

  self->GetInput()->Update();
  self->Finished = 1;

  return VTK_THREAD_RETURN_VALUE;
}

//----------------------------------------------------------------------------
// Access to Finished should have a mutex lock around it.
void vtkAsynchronousBuffer::UpdateInformation()
{
  if (this->Blocking)
    {
    this->BlockingUpdateInformation();
    }
  else
    {
    this->NonblockingUpdateInformation();
    }
}

//----------------------------------------------------------------------------
// Access to Finished should have a mutex lock around it.
void vtkAsynchronousBuffer::NonblockingUpdateInformation()
{
  vtkDataSet *input = this->GetInput();
  vtkDataSet *output = this->GetOutput();
  unsigned long t1, t2;

  // just some error checking
  if (input == NULL)
    {
    vtkErrorMacro("No Input");
    return;
    }
  if (output == NULL)
    {
    vtkErrorMacro("No Output");
    return;
    }

  // Avoid accessing input if another thread is running.
  // I assume values from last UpdateInformation is sufficient.
  if ( ! this->Finished)
    {
    vtkDebugMacro("Still Updating");
    return;
    }

  // Test to see if we can promote data (copy form input to output)
  // If last promotion has not been consumed.
  // (The existance of a thread is used to detect promotable data.)
  if (this->OutputConsumed && this->ThreadId != -1)
    {
    // Promote the data (copy input to output)
    this->PromoteData();
    this->OutputConsumed = 0;
    // clean up thread.
    vtkDebugMacro("Promoting data to output");
    this->Threader->TerminateThread(this->ThreadId);
    this->ThreadId = -1;
    // This modified will cause update to be called ...
    // (not really necessary, because output has been modified by promotion).
    this->Modified();
    }

  // Test to see if we should start an asynchronous update.
  // Only start an update if we are not updating already,
  // and there is no promotable data.
  if (this->ThreadId == -1)
    {
    // check the update time of the input directly to pre determine
    // whether input will generate new data.
    input->UpdateInformation();
    if (input->GetPipelineMTime() > input->GetUpdateTime())
      {
      // spawn a thread and start an update.
      // what if an abort occurs?!! ...
      vtkDebugMacro("Spawn an update");
      this->Finished = 0;
      this->ThreadId =
	this->Threader->SpawnThread(vtkAsynchronousBufferUpdate, (void *)this);
      }
    }

  // Do the typical update information stuff (as if we were a simple source).
  output->GetDataInformation()->SetLocality(1.0);
  t1 = this->GetMTime();
  t2 = output->GetMTime();
  if (t2 > t1)
    {
    t1 = t2;
    }
  output->SetPipelineMTime(t1);
  // Is it up to date? Really? Oh well.
  output->SetEstimatedWholeMemorySize(input->GetEstimatedWholeMemorySize());
  // Copy data specific information
  output->CopyInformation(input);
}

//----------------------------------------------------------------------------
// Access to Finished should have a mutex lock around it.
void vtkAsynchronousBuffer::BlockingUpdateInformation()
{
  vtkDataSet *input = this->GetInput();
  vtkDataSet *output = this->GetOutput();

  // just some error checking
  if (input == NULL)
    {
    vtkErrorMacro("No Input");
    return;
    }
  if (output == NULL)
    {
    vtkErrorMacro("No Output");
    return;
    }

  // make sure we are not already updating asynchronously.
  this->WaitForFinished();

  // Now we can look downstream for pipeline mtime.
  this->vtkSource::UpdateInformation();

  // Copy data specific information
  output->CopyInformation(input);
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::InternalUpdate(vtkDataObject *output)
{
  if (this->Blocking)
    {
    this->BlockingUpdate();
    }
  else
    {
    this->NonblockingUpdate();
    }
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::NonblockingUpdate()
{
  // Every thing has been done in UpdateInformation
  // Maybe we should leave the promotion to the update, but that might
  // cause a delay initiating the next asynchronous update.

  this->OutputConsumed = 1;
}

//----------------------------------------------------------------------------
// To make sure the data gets to output (for initialization)
// I am not positive this still works
void vtkAsynchronousBuffer::BlockingUpdate()
{
  if (this->GetInput() == NULL)
    {
    return;
    }

  // check to see if we are already updating (loop)
  if (this->Updating)
    {
    return;
    }

  // make sure we are not already updating asynchronously.
  this->WaitForFinished();

  // delete thread from last update (clean up)
  if (this->ThreadId != -1)
    {
    this->Threader->TerminateThread(this->ThreadId);
    this->ThreadId = -1;
    }

  // Do we need to update our input?
  if (this->GetInput()->GetUpdateTime() < this->GetInput()->GetPipelineMTime())
    {
    this->GetInput()->Update();
    }

  // This executes the copy if the input is more recent than the output
  this->PromoteData();
}

//----------------------------------------------------------------------------
// This may need a mutex lock.  I assume not because the spawned thread
// only set the variable to 1 at the end.  Any value of zero is ok,
// and any partial non zero value is ok too.
int vtkAsynchronousBuffer::TestForFinished()
{
  return (int)(this->Finished);
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::WaitForFinished()
{
  while ( ! this->Finished)
    {
    // vtkTimerLog::Sleep(10);
    }
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::PromoteData()
{
  if ( this->StartMethod )
    {
    (*this->StartMethod)(this->StartMethodArg);
    }
  this->Progress = 0.0;
  this->GetOutput()->Initialize(); //clear output
  this->Execute();
  if ( !this->AbortExecute )
    {
    this->UpdateProgress(1.0);
    }
  if ( this->EndMethod )
    {
    (*this->EndMethod)(this->EndMethodArg);
    }

  if ( this->GetInput()->ShouldIReleaseData() )
    {
    this->GetInput()->ReleaseData();
    }
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::Execute()
{
  this->GetOutput()->CopyStructure((vtkDataSet *)this->GetInput());

  this->GetOutput()->GetPointData()->PassData(
                 ((vtkDataSet *)this->GetInput())->GetPointData());
  this->GetOutput()->GetCellData()->PassData(
                 ((vtkDataSet *)this->GetInput())->GetCellData());
}

//----------------------------------------------------------------------------
void vtkAsynchronousBuffer::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataSetFilter::PrintSelf(os,indent);

  if (this->Blocking)
    {
    os << indent << "BlockingOn\n";
    }
  else
    {
    os << indent << "BlockingOff\n";
    }
  os << "Finished: " << this->Finished << endl;

  os << indent << "ThreadId: " << this->ThreadId << "\n";
}

<|endoftext|>


<commit_before>#include "llist.h"
#include <iostream>
#include <cassert>

typedef struct my_list {
    int value;
    sl_list_t nd;
} my_list;

//shabby way of creating node
static my_list nodes[] = {
     {10, 0}
    ,{20, 0}
    ,{30, 0}
    ,{40, 0}
    ,{50, 0}
    ,{60, 0}
    ,{70, 0}
    ,{80, 0}
    ,{90, 0}
    ,{100, 0}
};

#define ARRAY_SIZE(array) sizeof(array)/sizeof(array[0])

my_list* nth_from_end(sl_list_t *list, const int n)
{
    sl_list_t *rptr = NULL;
    sl_list_t *itr = list;
    assert( n > 0);
    for( int i = 0; i < n; ++i) {
        if (!itr) {
            std::cerr << "Either empty or list lesser than " << n
                << " passed" << std::endl;
            return NULL;
        }
        assert(itr != NULL);
        itr = itr->nxt;
    }

    for(rptr = list; itr; itr = itr->nxt)
    {
        rptr = rptr->nxt;
    }
    return SL_LIST_ENTRY(rptr, my_list, nd);
}

bool is_circular(sl_list_t *list)
{
    sl_list_t *slow_ptr = NULL;
    sl_list_t *fast_ptr = NULL;
    for(slow_ptr = list, fast_ptr = list; slow_ptr && fast_ptr && fast_ptr->nxt;
           slow_ptr = slow_ptr->nxt, fast_ptr = fast_ptr->nxt)
    {
        fast_ptr = fast_ptr->nxt;
        if ( slow_ptr == fast_ptr ) return true;
    }
    return false;
}

sl_list_t* find_loop_start(sl_list_t *list)
{
    sl_list_t *slow_ptr = NULL;
    sl_list_t *fast_ptr = NULL;
    bool is_circular = false;
    for(slow_ptr = list, fast_ptr = list; slow_ptr && fast_ptr && fast_ptr->nxt;
           fast_ptr = fast_ptr->nxt, slow_ptr = slow_ptr->nxt)
    {
        fast_ptr = fast_ptr->nxt;
        if ( slow_ptr == fast_ptr ) {
            is_circular = true;
            break;
        }
    }
    if (is_circular) {
        for( fast_ptr = list; slow_ptr != fast_ptr; slow_ptr = slow_ptr->nxt) {
     //       std::cout << (SL_LIST_ENTRY(slow_ptr, my_list, nd))->value << "\t" << (SL_LIST_ENTRY(fast_ptr, my_list, nd))->value << std::endl;
            fast_ptr = fast_ptr->nxt;
        }

        return slow_ptr;
    }
    return NULL;
}
int find_loop_len(sl_list_t *list)
{
    sl_list_t *slow_ptr = NULL;
    sl_list_t *fast_ptr = NULL;
    bool is_circular = false;
    for(slow_ptr = list, fast_ptr = list; slow_ptr && fast_ptr && fast_ptr->nxt;
           slow_ptr = slow_ptr->nxt, fast_ptr = fast_ptr->nxt)
    {
        fast_ptr = fast_ptr->nxt;
        if ( slow_ptr == fast_ptr ) {
            is_circular = true;
            break;
        }
    }
    int cnt = 0;
    if (is_circular) {
        for( ;slow_ptr != fast_ptr; fast_ptr = fast_ptr->nxt)
        {
            ++cnt;
        }
    }
    return cnt;
}

void test_nth_from_end(sl_list_t hdr)
{
    my_list *t = nth_from_end(hdr.nxt, 5);
    std::cout << t->value << std::endl;

    t = nth_from_end(hdr.nxt, 1);
    std::cout << t->value << std::endl;

    t = nth_from_end(hdr.nxt, 15);
    assert( t == NULL);
}

#define ENABLE_DEBG 1
int main(int argc, char *argv[])
{
    SL_LIST_HD(hdr);
    for (int i = 0; i < ARRAY_SIZE(nodes); ++i) {
        insert(&(nodes[ARRAY_SIZE(nodes) - (i + 1)].nd) , &hdr);
    }

#if ENABLE_DEBG
    sl_list_t *ptr = NULL;
    SL_FOR_EACH(ptr, hdr.nxt) {
        my_list  *p = SL_LIST_ENTRY(ptr, my_list, nd);
        std::cout << p->value << std::endl;
    }
#endif
//    test_nth_from_end( hdr);

    //test floyd algo
    nodes[9].nd.nxt = nodes[4].nd.nxt;

    assert(is_circular(hdr.nxt));
//    std::cout << (SL_LIST_ENTRY(find_loop_start(hdr.nxt), my_list, nd))->value << std::endl;
#if ENABLE_DEBG
    SL_FOR_EACH(ptr, hdr.nxt) {
        my_list  *p = SL_LIST_ENTRY(ptr, my_list, nd);
        std::cout << p->value << std::endl;
    }
#endif

    nodes[9].nd.nxt = NULL;
    assert(!is_circular(hdr.nxt));
    nodes[9].nd.nxt = nodes[0].nd.nxt;
    assert(is_circular(hdr.nxt));
}
<commit_msg>fix loop detection logic<commit_after>#include "llist.h"
#include <iostream>
#include <cassert>

typedef struct my_list {
    int value;
    sl_list_t nd;
} my_list;

//shabby way of creating node
static my_list nodes[] = {
     {10, 0}
    ,{20, 0}
    ,{30, 0}
    ,{40, 0}
    ,{50, 0}
    ,{60, 0}
    ,{70, 0}
    ,{80, 0}
    ,{90, 0}
    ,{100, 0}
};

#define ARRAY_SIZE(array) sizeof(array)/sizeof(array[0])

my_list* nth_from_end(sl_list_t *list, const int n)
{
    sl_list_t *rptr = NULL;
    sl_list_t *itr = list;
    assert( n > 0);
    for( int i = 0; i < n; ++i) {
        if (!itr) {
            std::cerr << "Either empty or list lesser than " << n
                << " passed" << std::endl;
            return NULL;
        }
        assert(itr != NULL);
        itr = itr->nxt;
    }

    for(rptr = list; itr; itr = itr->nxt)
    {
        rptr = rptr->nxt;
    }
    return SL_LIST_ENTRY(rptr, my_list, nd);
}

bool is_circular(sl_list_t *list)
{
    sl_list_t *slow_ptr = list;
    sl_list_t *fast_ptr = list;
    for(; slow_ptr && fast_ptr && fast_ptr->nxt && fast_ptr->nxt->nxt;
           )
    {
        slow_ptr = slow_ptr->nxt;
        fast_ptr = fast_ptr->nxt->nxt;
        if ( slow_ptr == fast_ptr ) return true;
    }
    return false;
}

sl_list_t* find_loop_start(sl_list_t *list)
{
    sl_list_t *slow_ptr = list;
    sl_list_t *fast_ptr = list;
    bool is_circular = false;

    for(; slow_ptr && fast_ptr && fast_ptr->nxt && fast_ptr->nxt->nxt;)
    {
        slow_ptr = slow_ptr->nxt;
        fast_ptr = fast_ptr->nxt->nxt;
        if ( slow_ptr == fast_ptr ) {
            is_circular = true;
            break;
        }
    }

    if (is_circular) {
        for( fast_ptr = list; slow_ptr != fast_ptr; slow_ptr = slow_ptr->nxt, fast_ptr = fast_ptr->nxt) {
            ;
        }

        return slow_ptr;
    }
    return NULL;
}
int find_loop_len(sl_list_t *list)
{
    sl_list_t *slow_ptr = list;
    sl_list_t *fast_ptr = list;
    bool is_circular = false;

    for(; slow_ptr && fast_ptr && fast_ptr->nxt && fast_ptr->nxt->nxt;)
    {
        slow_ptr = slow_ptr->nxt;
        fast_ptr = fast_ptr->nxt->nxt;
        if ( slow_ptr == fast_ptr ) {
            is_circular = true;
            break;
        }
    }
    int cnt = 0;
    if (is_circular) {
        for( ;slow_ptr != fast_ptr; fast_ptr = fast_ptr->nxt)
        {
            ++cnt;
        }
    }
    return cnt;
}

void test_nth_from_end(sl_list_t hdr)
{
    my_list *t = nth_from_end(hdr.nxt, 5);
    std::cout << t->value << std::endl;

    t = nth_from_end(hdr.nxt, 1);
    std::cout << t->value << std::endl;

    t = nth_from_end(hdr.nxt, 15);
    assert( t == NULL);
}

#define ENABLE_DEBG 0
int main(int argc, char *argv[])
{
    SL_LIST_HD(hdr);
    for (int i = 0; i < ARRAY_SIZE(nodes); ++i) {
        insert(&(nodes[ARRAY_SIZE(nodes) - (i + 1)].nd) , &hdr);
    }

#if ENABLE_DEBG
    sl_list_t *ptr = NULL;
    SL_FOR_EACH(ptr, hdr.nxt) {
        my_list  *p = SL_LIST_ENTRY(ptr, my_list, nd);
        std::cout << p->value << std::endl;
    }
#endif
    test_nth_from_end( hdr);

    //test floyd algo
    nodes[9].nd.nxt = nodes[4].nd.nxt;

    assert(is_circular(hdr.nxt));

    nodes[9].nd.nxt = NULL;
    assert(!is_circular(hdr.nxt));
    nodes[9].nd.nxt = nodes[0].nd.nxt;
    assert(is_circular(hdr.nxt));
}
<|endoftext|>


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

#ifndef PS_CORE_UNIQUE_RESOURCE_HPP
#define PS_CORE_UNIQUE_RESOURCE_HPP

#if __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#elif _WIN32
#include <prosoft/core/config/config_windows.h>
#include <windows.h>
#endif

#include <cstring> // memset
#include <memory>
#include <type_traits>
#include <utility>

#include <prosoft/core/config/config.h>

namespace prosoft {

// malloc for typed anonymous memory
namespace iunique {
struct malloc_delete {
    void operator()(void* p) PS_NOEXCEPT {
        std::free(p);
    }
};
} // iunique

template <typename T>
using unique_malloc = std::unique_ptr<T, iunique::malloc_delete>;

template <typename T>
inline unique_malloc<T> make_malloc(size_t sz) PS_NOEXCEPT {
    return unique_malloc<T>{ (T*)std::malloc(sz) };
}

struct count_t {
    explicit count_t(size_t ct) PS_NOEXCEPT : count(ct) {}
    size_t count;
};

template <typename T>
inline unique_malloc<T> make_malloc(count_t count) PS_NOEXCEPT {
    return unique_malloc<T>{ (T*)std::malloc(sizeof(T) * count.count) };
}

template <typename T>
inline unique_malloc<T> init_malloc(size_t sz, int pattern = 0) PS_NOEXCEPT {
    auto p = make_malloc<T>(sz);
    if (p) {
        std::memset(p.get(), pattern, sz);
    }
    return p;
}

template <typename T>
inline unique_malloc<T> make_malloc(size_t count, size_t sz) PS_NOEXCEPT {
    return unique_malloc<T>{ (T*)std::calloc(count, sz) };
}

template <typename T>
inline unique_malloc<T>& make_malloc(unique_malloc<T>& ptr, size_t sz) PS_NOEXCEPT {
    auto p = ptr.release(); // don't free old ptr
    ptr.reset((T*)std::realloc(p, sz));
    return ptr;
}

template <typename T, typename... Args>
inline unique_malloc<T> make_malloc_throw(Args&&... args) {
    auto p = make_malloc<T>(std::forward<Args>(args)...);
    PS_THROW_IF(!p, std::bad_alloc());
    return p;
}

#if __APPLE__

namespace iunique {
// CF ref types can be both non-const and const
struct cf_delete {
    void operator()(void* p) PS_NOEXCEPT {
        if (p) { ::CFRelease(p); }
    }
    void operator()(const void* p) PS_NOEXCEPT {
        if (p) { ::CFRelease(p); }
    }
};
} // iunique

template <typename CFRefType>
using unique_cftype = std::unique_ptr<typename std::remove_pointer<CFRefType>::type, iunique::cf_delete>;

namespace CF {
// Common CF type aliases
using unique_array = unique_cftype<CFArrayRef>;
using unique_data = unique_cftype<CFDataRef>;
using unique_dictionary = unique_cftype<CFDictionaryRef>;
using unique_error = unique_cftype<CFErrorRef>;
using unique_number = unique_cftype<CFNumberRef>;
using unique_string = unique_cftype<CFStringRef>;
using unique_type = unique_cftype<CFTypeRef>;
using unique_url = unique_cftype<CFURLRef>;
} // CF

#elif _WIN32

namespace iunique {
struct global_delete {
    void operator() (void* p) PS_NOEXCEPT {
        ::GlobalFree(p);
    }
};
// XXX: Heap allocation requires external context other than the pointer and would thus be hard to implement as a unique_ptr.
struct local_delete {
    void operator() (void* p) PS_NOEXCEPT {
        ::LocalFree(p);
    }
};
struct taskmem_delete {
    void operator() (void* p) noexcept {
        ::CoTaskMemFree(p);
    }
};
} // iunique

namespace windows {
template <typename T>
using unique_global = std::unique_ptr<T, iunique::global_delete>;

template <typename T>
using unique_local = std::unique_ptr<T, iunique::local_delete>;

template <typename T>
using unique_taskmem = std::unique_ptr<T, iunique::taskmem_delete>;

struct handle_traits {
    typedef HANDLE pointer;

    bool is_valid(pointer p) const PS_NOEXCEPT {
        return (p && p != INVALID_HANDLE_VALUE);
    }

    void operator()(pointer p) PS_NOEXCEPT {
        if (is_valid(p)) {
            ::CloseHandle(p);
        }
    }
};

// Custom class for HANDLE's, mainly because std::unique_ptr does not have a way to customize the invalid ptr value.
// See http://blogs.msdn.com/b/oldnewthing/archive/2004/03/02/82639.aspx for further HANDLE pitfalls.
template <class Ptr, class Traits>
class unique_handle {
    using up_type = std::unique_ptr<typename std::remove_pointer<Ptr>::type, Traits>;
    up_type m_up;
public:
    typedef typename up_type::element_type element_type;
    typedef typename up_type::deleter_type deleter_type;
    typedef typename up_type::pointer pointer;

    PS_DEFAULT_CONSTRUCTOR(unique_handle);
    PS_DEFAULT_DESTRUCTOR(unique_handle);
    PS_DISABLE_COPY(unique_handle);
    PS_DEFAULT_MOVE(unique_handle);

    unique_handle(Ptr p) PS_NOEXCEPT : m_up(p) {}

    Ptr get() const PS_NOEXCEPT { return m_up.get(); }
    // XXX: HANDLE is void, so operator* and -> make no sense.
    explicit operator bool() const PS_NOEXCEPT { return m_up.get_deleter().is_valid(get()); }

    Ptr release() PS_NOEXCEPT { return m_up.release(); }
    void reset(Ptr p = Ptr{}) PS_NOEXCEPT { m_up.reset(p); }
    void operator=(std::nullptr_t) PS_NOEXCEPT { reset(); }
    void swap(unique_handle& uh) PS_NOEXCEPT { m_up.swap(uh.m_up); }
};

using Handle = unique_handle<HANDLE, handle_traits>;

} // windows

#endif // __APPLE__

// CF and Win APIs use handles (the ptr-to-ptr type) quite a lot.
namespace iunique {
template <class T, class D, class UPtr>
class uphandle;

template <class Up>
using uphandle_t = uphandle<typename Up::element_type, typename Up::deleter_type, typename std::decay<Up>::type>;
}

template <class Up>
iunique::uphandle_t<Up> handle(Up&) PS_NOEXCEPT;

namespace iunique {

template <class T, class D, class UPtr>
class uphandle {
    using upointer = UPtr;
    using pointer = typename upointer::pointer;
    upointer* m_u;
    pointer m_p;

    void store() PS_NOEXCEPT {
        if (m_u) {
            m_u->reset(m_p);
        }
    }

    uphandle(upointer& up) PS_NOEXCEPT : m_u(&up), m_p(nullptr) {}

    uphandle(uphandle&& other)
        : m_u(other.m_u)
        , m_p(other.m_p) {
        other.m_u = nullptr;
        other.m_p = nullptr;
    }

    friend uphandle prosoft::handle<upointer>(upointer&) PS_NOEXCEPT;

public:
    // Disabling copy and making construct and move private means this class can never bind to an external lvalue.
    // This would be dangerous as leaks coud occur quite easily since the backing store sync only happens on destruction.
    PS_DISABLE_DEFAULT_CONSTRUCTOR(uphandle);
    PS_DISABLE_COPY(uphandle);

    ~uphandle() PS_NOEXCEPT {
        store();
    }

    operator pointer*() { return &m_p; }
};

} // iunique

template <class Up>
iunique::uphandle_t<Up> handle(Up& up) PS_NOEXCEPT {
    return iunique::uphandle_t<Up>{up};
}

} // prosoft

#endif // PS_CORE_UNIQUE_RESOURCE_HPP
<commit_msg>Add ability to specify deleter for unique_cftype<commit_after>// Copyright © 2013-2015, Prosoft Engineering, Inc. (A.K.A "Prosoft")
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Prosoft nor the names of its contributors may be
//       used to endorse or promote products derived from this software without
//       specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL PROSOFT ENGINEERING, INC. BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef PS_CORE_UNIQUE_RESOURCE_HPP
#define PS_CORE_UNIQUE_RESOURCE_HPP

#if __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#elif _WIN32
#include <prosoft/core/config/config_windows.h>
#include <windows.h>
#endif

#include <cstring> // memset
#include <memory>
#include <type_traits>
#include <utility>

#include <prosoft/core/config/config.h>

namespace prosoft {

// malloc for typed anonymous memory
namespace iunique {
struct malloc_delete {
    void operator()(void* p) PS_NOEXCEPT {
        std::free(p);
    }
};
} // iunique

template <typename T>
using unique_malloc = std::unique_ptr<T, iunique::malloc_delete>;

template <typename T>
inline unique_malloc<T> make_malloc(size_t sz) PS_NOEXCEPT {
    return unique_malloc<T>{ (T*)std::malloc(sz) };
}

struct count_t {
    explicit count_t(size_t ct) PS_NOEXCEPT : count(ct) {}
    size_t count;
};

template <typename T>
inline unique_malloc<T> make_malloc(count_t count) PS_NOEXCEPT {
    return unique_malloc<T>{ (T*)std::malloc(sizeof(T) * count.count) };
}

template <typename T>
inline unique_malloc<T> init_malloc(size_t sz, int pattern = 0) PS_NOEXCEPT {
    auto p = make_malloc<T>(sz);
    if (p) {
        std::memset(p.get(), pattern, sz);
    }
    return p;
}

template <typename T>
inline unique_malloc<T> make_malloc(size_t count, size_t sz) PS_NOEXCEPT {
    return unique_malloc<T>{ (T*)std::calloc(count, sz) };
}

template <typename T>
inline unique_malloc<T>& make_malloc(unique_malloc<T>& ptr, size_t sz) PS_NOEXCEPT {
    auto p = ptr.release(); // don't free old ptr
    ptr.reset((T*)std::realloc(p, sz));
    return ptr;
}

template <typename T, typename... Args>
inline unique_malloc<T> make_malloc_throw(Args&&... args) {
    auto p = make_malloc<T>(std::forward<Args>(args)...);
    PS_THROW_IF(!p, std::bad_alloc());
    return p;
}

#if __APPLE__

namespace iunique {
// CF ref types can be both non-const and const
struct cf_delete {
    void operator()(void* p) PS_NOEXCEPT {
        if (p) { ::CFRelease(p); }
    }
    void operator()(const void* p) PS_NOEXCEPT {
        if (p) { ::CFRelease(p); }
    }
};
} // iunique

template <typename CFRefType, class Deleter = iunique::cf_delete>
using unique_cftype = std::unique_ptr<typename std::remove_pointer<CFRefType>::type, Deleter>;

namespace CF {
// Common CF type aliases
using unique_array = unique_cftype<CFArrayRef>;
using unique_data = unique_cftype<CFDataRef>;
using unique_dictionary = unique_cftype<CFDictionaryRef>;
using unique_error = unique_cftype<CFErrorRef>;
using unique_number = unique_cftype<CFNumberRef>;
using unique_string = unique_cftype<CFStringRef>;
using unique_type = unique_cftype<CFTypeRef>;
using unique_url = unique_cftype<CFURLRef>;
} // CF

#elif _WIN32

namespace iunique {
struct global_delete {
    void operator() (void* p) PS_NOEXCEPT {
        ::GlobalFree(p);
    }
};
// XXX: Heap allocation requires external context other than the pointer and would thus be hard to implement as a unique_ptr.
struct local_delete {
    void operator() (void* p) PS_NOEXCEPT {
        ::LocalFree(p);
    }
};
struct taskmem_delete {
    void operator() (void* p) noexcept {
        ::CoTaskMemFree(p);
    }
};
} // iunique

namespace windows {
template <typename T>
using unique_global = std::unique_ptr<T, iunique::global_delete>;

template <typename T>
using unique_local = std::unique_ptr<T, iunique::local_delete>;

template <typename T>
using unique_taskmem = std::unique_ptr<T, iunique::taskmem_delete>;

struct handle_traits {
    typedef HANDLE pointer;

    bool is_valid(pointer p) const PS_NOEXCEPT {
        return (p && p != INVALID_HANDLE_VALUE);
    }

    void operator()(pointer p) PS_NOEXCEPT {
        if (is_valid(p)) {
            ::CloseHandle(p);
        }
    }
};

// Custom class for HANDLE's, mainly because std::unique_ptr does not have a way to customize the invalid ptr value.
// See http://blogs.msdn.com/b/oldnewthing/archive/2004/03/02/82639.aspx for further HANDLE pitfalls.
template <class Ptr, class Traits>
class unique_handle {
    using up_type = std::unique_ptr<typename std::remove_pointer<Ptr>::type, Traits>;
    up_type m_up;
public:
    typedef typename up_type::element_type element_type;
    typedef typename up_type::deleter_type deleter_type;
    typedef typename up_type::pointer pointer;

    PS_DEFAULT_CONSTRUCTOR(unique_handle);
    PS_DEFAULT_DESTRUCTOR(unique_handle);
    PS_DISABLE_COPY(unique_handle);
    PS_DEFAULT_MOVE(unique_handle);

    unique_handle(Ptr p) PS_NOEXCEPT : m_up(p) {}

    Ptr get() const PS_NOEXCEPT { return m_up.get(); }
    // XXX: HANDLE is void, so operator* and -> make no sense.
    explicit operator bool() const PS_NOEXCEPT { return m_up.get_deleter().is_valid(get()); }

    Ptr release() PS_NOEXCEPT { return m_up.release(); }
    void reset(Ptr p = Ptr{}) PS_NOEXCEPT { m_up.reset(p); }
    void operator=(std::nullptr_t) PS_NOEXCEPT { reset(); }
    void swap(unique_handle& uh) PS_NOEXCEPT { m_up.swap(uh.m_up); }
};

using Handle = unique_handle<HANDLE, handle_traits>;

} // windows

#endif // __APPLE__

// CF and Win APIs use handles (the ptr-to-ptr type) quite a lot.
namespace iunique {
template <class T, class D, class UPtr>
class uphandle;

template <class Up>
using uphandle_t = uphandle<typename Up::element_type, typename Up::deleter_type, typename std::decay<Up>::type>;
}

template <class Up>
iunique::uphandle_t<Up> handle(Up&) PS_NOEXCEPT;

namespace iunique {

template <class T, class D, class UPtr>
class uphandle {
    using upointer = UPtr;
    using pointer = typename upointer::pointer;
    upointer* m_u;
    pointer m_p;

    void store() PS_NOEXCEPT {
        if (m_u) {
            m_u->reset(m_p);
        }
    }

    uphandle(upointer& up) PS_NOEXCEPT : m_u(&up), m_p(nullptr) {}

    uphandle(uphandle&& other)
        : m_u(other.m_u)
        , m_p(other.m_p) {
        other.m_u = nullptr;
        other.m_p = nullptr;
    }

    friend uphandle prosoft::handle<upointer>(upointer&) PS_NOEXCEPT;

public:
    // Disabling copy and making construct and move private means this class can never bind to an external lvalue.
    // This would be dangerous as leaks coud occur quite easily since the backing store sync only happens on destruction.
    PS_DISABLE_DEFAULT_CONSTRUCTOR(uphandle);
    PS_DISABLE_COPY(uphandle);

    ~uphandle() PS_NOEXCEPT {
        store();
    }

    operator pointer*() { return &m_p; }
};

} // iunique

template <class Up>
iunique::uphandle_t<Up> handle(Up& up) PS_NOEXCEPT {
    return iunique::uphandle_t<Up>{up};
}

} // prosoft

#endif // PS_CORE_UNIQUE_RESOURCE_HPP
<|endoftext|>


<commit_before>/* Copyright 2011, Carlos Guerreiro
 * http://perceptiveconstructs.com
 * Licensed under the MIT license */

#include <cstring>
#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <google/sparse_hash_map>
#include <google/dense_hash_map>

#include "MurmurHash3.h"

#include <map>

using google::sparse_hash_map;
using google::dense_hash_map;

using namespace std;

using namespace v8;
using namespace node;

struct RawHashKey {
  RawHashKey() : len(0), data(0) {
  }
  RawHashKey(size_t l, void* d) : len(l), data(d) {}
  size_t len;
  void* data;
};

struct BufferHasher {
  uint32_t seed;
  BufferHasher(void) : seed(1) {
  }
  BufferHasher(uint32_t s) : seed(s) {
  }
  size_t operator ()(const RawHashKey& k) const {
    uint32_t out;
    if(k.len == 0 || k.len == 0xffffffff)
      return 0;
    MurmurHash3_x86_32(k.data, k.len, seed, &out);
    return out;
  }
};

struct BufferEq {
  BufferEq(void) {
  }
  bool operator()(const RawHashKey& a, const RawHashKey& b) const {
    if(a.len != b.len)
      return false;
    if(a.len == 0 || a.len == 0xffffffff)
      return true;
    return memcmp(a.data, b.data, a.len) == 0;
  }
};

// used by MapRawHash (std::map) only
// doesn't have to deal with special values for deleted or empty
struct BufferLess {
  BufferLess(void) {
  }
  bool operator()(const RawHashKey& a, const RawHashKey& b) const {
    if(a.len == b.len)
      return memcmp(a.data, b.data, a.len) < 0;
    else
      return a.len < b.len;
  }
};

RawHashKey empty(0, 0);
RawHashKey deleted(0xffffffff, 0);

void initPostConstruction(sparse_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq>& m) {
  m.set_deleted_key(deleted);
}

void initPostConstruction(dense_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq>& m) {
  m.set_empty_key(empty);
  m.set_deleted_key(deleted);
}

void initPostConstruction(map<RawHashKey, Persistent<Value>, BufferLess>& m) {
}

template <class StorageT>
class RawHash: ObjectWrap {
private:
  StorageT items;

  typename StorageT::iterator access(Local<Value> v) {
    Local<Object> o = v->ToObject();
    RawHashKey pk(Buffer::Length(o), Buffer::Data(o));
    return items.find(pk);
  }
public:
  RawHash() : items() {
    initPostConstruction(items);
  }
  RawHash(uint32_t seed) : items(0, BufferHasher(seed)) {
    initPostConstruction(items);
  }

  ~RawHash() {
    typename StorageT::iterator it;

    for(it = items.begin(); it != items.end(); ++it) {
      free(it->first.data);
      it->second.Dispose();
    }
  }

  static void init(Handle < Object > target, Handle<Value> (*func)(const Arguments&), Persistent<FunctionTemplate>& ct, const char* name) {
    Local<FunctionTemplate> t = FunctionTemplate::New(func);
    ct = Persistent<FunctionTemplate>::New(t);
    ct->InstanceTemplate()->SetInternalFieldCount(1);
    Local<String> nameSymbol = String::NewSymbol(name);
    ct->SetClassName(nameSymbol);
    NODE_SET_PROTOTYPE_METHOD(ct, "set", set);
    NODE_SET_PROTOTYPE_METHOD(ct, "get", get);
    NODE_SET_PROTOTYPE_METHOD(ct, "del", del);
    NODE_SET_PROTOTYPE_METHOD(ct, "each", each);
    target->Set(nameSymbol, ct->GetFunction());
  }

  static Handle<Value> New(const Arguments& args) {
    HandleScope scope;

    if (!args.IsConstructCall()) {
      return ThrowException(Exception::TypeError(String::New("Use the new operator to create instances of this object.")));
    }

    RawHash* bh = new RawHash();
    bh->Wrap(args.This());
    return args.This();
  }

  static Handle<Value> NewWithSeed(const Arguments& args) {
    HandleScope scope;

    if (!args.IsConstructCall()) {
      return ThrowException(Exception::TypeError(String::New("Use the new operator to create instances of this object.")));
    }

    uint32_t seed = 1;
    if(args.Length() >= 1) {
      Local<Integer> s = *args[0]->ToInteger();
      if(s.IsEmpty())
	return Exception::Error(String::New("argument 1 must be a integer"));
      seed = s->Value();
    }
    RawHash* bh = new RawHash(seed);
    bh->Wrap(args.This());
    return args.This();
  }

  static Handle<Value> get(const Arguments& args) {
    HandleScope scope;

    if(args.Length() != 1) {
      return Exception::Error(String::New("get takes 1 argument"));
    }

    if(!Buffer::HasInstance(args[0]))
      return Exception::Error(String::New("argument 1 must be a Buffer"));

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());
    typename StorageT::iterator it = bh->access(args[0]);
    if(it == bh->items.end())
      return Undefined();

    return scope.Close(it->second);
  }

  static Handle<Value> set(const Arguments& args) {
    HandleScope scope;

    if(args.Length() != 2) {
      return Exception::Error(String::New("set takes 2 arguments"));
    }

    if(!Buffer::HasInstance(args[0]))
      return Exception::Error(String::New("argument 1 must be a Buffer"));

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());

    Persistent<Value> pv = Persistent<Value>::New(args[1]);
    Local<Object> o = args[0]->ToObject();

    RawHashKey pk;
    pk.len = Buffer::Length(o);
    pk.data = malloc(pk.len);
    memcpy(pk.data, Buffer::Data(o), pk.len);

    typename StorageT::iterator it = bh->items.find(pk);
    if(it != bh->items.end()) {
      it->second.Dispose();
      it->second = pv;
    } else
      bh->items[pk] = pv;

    return scope.Close(args[1]);
  }

  static Handle<Value> del(const Arguments& args) {
    HandleScope scope;

    if(args.Length() != 1) {
      return Exception::Error(String::New("get takes 1 argument"));
    }

    if(!Buffer::HasInstance(args[0]))
      return Exception::Error(String::New("argument 1 must be a Buffer"));

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());
    typename StorageT::iterator it = bh->access(args[0]);
    if(it == bh->items.end())
      return scope.Close(Boolean::New(false));

    free(it->first.data);
    it->second.Dispose();
    bh->items.erase(it);

    return scope.Close(Boolean::New(true));
  }

  static Handle<Value> each(const Arguments& args) {
    if(args.Length() != 1) {
      return Exception::Error(String::New("each takes 1 argument"));
    }
    if (!args[0]->IsFunction()) {
      return ThrowException(Exception::TypeError(String::New("argument must be a callback function")));
    }
    // There's no ToFunction(), use a Cast instead.
    Local<Function> callback = Local<Function>::Cast(args[0]);
    Local<Value> k = Local<Value>::New(Undefined());
    Local<Value> v = Local<Value>::New(Undefined());

    const unsigned argc = 2;
    Local<Value> argv[argc] = { v };

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());
    typename StorageT::iterator it;

    Local<Object> globalObj = Context::GetCurrent()->Global();
    Local<Function> bufferConstructor = Local<Function>::Cast(globalObj->Get(String::New("Buffer")));

    for(it = bh->items.begin(); it != bh->items.end(); ++it) {
      const RawHashKey& k = it->first;
      Buffer* b = Buffer::New(k.len);
      memcpy(Buffer::Data(b), k.data, k.len);
      // FIXME: consider not creating a Buffer object every time
      argv[0] = Local<Value>::New(b->handle_);
      argv[1] = *it->second;
      TryCatch tc;
      Local<Value> ret = callback->Call(Context::GetCurrent()->Global(), argc, argv);
      if(ret.IsEmpty() || ret->IsFalse())
	break;
    }

    return Undefined();
  }
};

typedef RawHash<sparse_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq> > SparseRawHash;
typedef RawHash<dense_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq> > DenseRawHash;
typedef RawHash<map<RawHashKey, Persistent<Value>, BufferLess> > MapRawHash;

static Persistent<FunctionTemplate> sparseRawHash_ct;
static Persistent<FunctionTemplate> denseRawHash_ct;
static Persistent<FunctionTemplate> mapRawHash_ct;

void RegisterModule(Handle<Object> target) {
  SparseRawHash::init(target, SparseRawHash::NewWithSeed, sparseRawHash_ct, "Sparse");
  DenseRawHash::init(target, DenseRawHash::NewWithSeed, denseRawHash_ct, "Dense");
  MapRawHash::init(target, MapRawHash::New, mapRawHash_ct, "Map");
}

NODE_MODULE(rawhash, RegisterModule);
<commit_msg>throwing exceptions properly. some formatting fixes. removed some dead code.<commit_after>/* Copyright 2011, Carlos Guerreiro
 * http://perceptiveconstructs.com
 * Licensed under the MIT license */

#include <cstring>
#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <google/sparse_hash_map>
#include <google/dense_hash_map>

#include "MurmurHash3.h"

#include <map>

using google::sparse_hash_map;
using google::dense_hash_map;

using namespace std;

using namespace v8;
using namespace node;

struct RawHashKey {
  RawHashKey() : len(0), data(0) {
  }
  RawHashKey(size_t l, void* d) : len(l), data(d) {}
  size_t len;
  void* data;
};

struct BufferHasher {
  uint32_t seed;
  BufferHasher(void) : seed(1) {
  }
  BufferHasher(uint32_t s) : seed(s) {
  }
  size_t operator ()(const RawHashKey& k) const {
    uint32_t out;
    if(k.len == 0 || k.len == 0xffffffff)
      return 0;
    MurmurHash3_x86_32(k.data, k.len, seed, &out);
    return out;
  }
};

struct BufferEq {
  BufferEq(void) {
  }
  bool operator()(const RawHashKey& a, const RawHashKey& b) const {
    if(a.len != b.len)
      return false;
    if(a.len == 0 || a.len == 0xffffffff)
      return true;
    return memcmp(a.data, b.data, a.len) == 0;
  }
};

// used by MapRawHash (std::map) only
// doesn't have to deal with special values for deleted or empty
struct BufferLess {
  BufferLess(void) {
  }
  bool operator()(const RawHashKey& a, const RawHashKey& b) const {
    if(a.len == b.len)
      return memcmp(a.data, b.data, a.len) < 0;
    else
      return a.len < b.len;
  }
};

RawHashKey empty(0, 0);
RawHashKey deleted(0xffffffff, 0);

void initPostConstruction(sparse_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq>& m) {
  m.set_deleted_key(deleted);
}

void initPostConstruction(dense_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq>& m) {
  m.set_empty_key(empty);
  m.set_deleted_key(deleted);
}

void initPostConstruction(map<RawHashKey, Persistent<Value>, BufferLess>& m) {
}

template <class StorageT>
class RawHash: ObjectWrap {
private:
  StorageT items;

  typename StorageT::iterator access(Local<Value> v) {
    Local<Object> o = v->ToObject();
    RawHashKey pk(Buffer::Length(o), Buffer::Data(o));
    return items.find(pk);
  }
public:
  RawHash() : items() {
    initPostConstruction(items);
  }
  RawHash(uint32_t seed) : items(0, BufferHasher(seed)) {
    initPostConstruction(items);
  }

  ~RawHash() {
    typename StorageT::iterator it;

    for(it = items.begin(); it != items.end(); ++it) {
      free(it->first.data);
      it->second.Dispose();
    }
  }

  static void init(Handle < Object > target, Handle<Value> (*func)(const Arguments&), Persistent<FunctionTemplate>& ct, const char* name) {
    Local<FunctionTemplate> t = FunctionTemplate::New(func);
    ct = Persistent<FunctionTemplate>::New(t);
    ct->InstanceTemplate()->SetInternalFieldCount(1);
    Local<String> nameSymbol = String::NewSymbol(name);
    ct->SetClassName(nameSymbol);
    NODE_SET_PROTOTYPE_METHOD(ct, "set", set);
    NODE_SET_PROTOTYPE_METHOD(ct, "get", get);
    NODE_SET_PROTOTYPE_METHOD(ct, "del", del);
    NODE_SET_PROTOTYPE_METHOD(ct, "each", each);
    target->Set(nameSymbol, ct->GetFunction());
  }

  static Handle<Value> New(const Arguments& args) {
    HandleScope scope;

    if (!args.IsConstructCall()) {
      return ThrowException(Exception::TypeError(String::New("Use the new operator to create instances of this object.")));
    }

    RawHash* bh = new RawHash();
    bh->Wrap(args.This());
    return args.This();
  }

  static Handle<Value> NewWithSeed(const Arguments& args) {
    HandleScope scope;

    if (!args.IsConstructCall()) {
      return ThrowException(Exception::TypeError(String::New("Use the new operator to create instances of this object.")));
    }

    uint32_t seed = 1;
    if(args.Length() >= 1) {
      Local<Integer> s = *args[0]->ToInteger();
      if(s.IsEmpty())
        return ThrowException(Exception::Error(String::New("argument 1 must be a integer")));
      seed = s->Value();
    }
    RawHash* bh = new RawHash(seed);
    bh->Wrap(args.This());
    return args.This();
  }

  static Handle<Value> get(const Arguments& args) {
    HandleScope scope;

    if(args.Length() != 1) {
      return ThrowException(Exception::Error(String::New("get takes 1 argument")));
    }

    if(!Buffer::HasInstance(args[0]))
      return ThrowException(Exception::Error(String::New("argument 1 must be a Buffer")));

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());
    typename StorageT::iterator it = bh->access(args[0]);
    if(it == bh->items.end())
      return Undefined();

    return scope.Close(it->second);
  }

  static Handle<Value> set(const Arguments& args) {
    HandleScope scope;

    if(args.Length() != 2) {
      return ThrowException(Exception::Error(String::New("set takes 2 arguments")));
    }

    if(!Buffer::HasInstance(args[0]))
      return ThrowException(Exception::Error(String::New("argument 1 must be a Buffer")));

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());

    Persistent<Value> pv = Persistent<Value>::New(args[1]);
    Local<Object> o = args[0]->ToObject();

    RawHashKey pk;
    pk.len = Buffer::Length(o);
    pk.data = malloc(pk.len);
    memcpy(pk.data, Buffer::Data(o), pk.len);

    typename StorageT::iterator it = bh->items.find(pk);
    if(it != bh->items.end()) {
      it->second.Dispose();
      it->second = pv;
    } else
      bh->items[pk] = pv;

    return scope.Close(args[1]);
  }

  static Handle<Value> del(const Arguments& args) {
    HandleScope scope;

    if(args.Length() != 1) {
      return ThrowException(Exception::Error(String::New("get takes 1 argument")));
    }

    if(!Buffer::HasInstance(args[0]))
      return ThrowException(Exception::Error(String::New("argument 1 must be a Buffer")));

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());
    typename StorageT::iterator it = bh->access(args[0]);
    if(it == bh->items.end())
      return scope.Close(Boolean::New(false));

    free(it->first.data);
    it->second.Dispose();
    bh->items.erase(it);

    return scope.Close(Boolean::New(true));
  }

  static Handle<Value> each(const Arguments& args) {
    if(args.Length() != 1) {
      return ThrowException(Exception::Error(String::New("each takes 1 argument")));
    }
    if (!args[0]->IsFunction()) {
      return ThrowException(Exception::TypeError(String::New("argument must be a callback function")));
    }
    // There's no ToFunction(), use a Cast instead.
    Local<Function> callback = Local<Function>::Cast(args[0]);
    Local<Value> k = Local<Value>::New(Undefined());
    Local<Value> v = Local<Value>::New(Undefined());

    const unsigned argc = 2;
    Local<Value> argv[argc] = { v };

    RawHash* bh = ObjectWrap::Unwrap<RawHash>(args.This());
    typename StorageT::iterator it;

    for(it = bh->items.begin(); it != bh->items.end(); ++it) {
      const RawHashKey& k = it->first;
      Buffer* b = Buffer::New(k.len);
      memcpy(Buffer::Data(b), k.data, k.len);
      // FIXME: consider not creating a Buffer object every time
      argv[0] = Local<Value>::New(b->handle_);
      argv[1] = *it->second;
      TryCatch tc;
      Local<Value> ret = callback->Call(Context::GetCurrent()->Global(), argc, argv);
      if(ret.IsEmpty() || ret->IsFalse())
        break;
    }

    return Undefined();
  }
};

typedef RawHash<sparse_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq> > SparseRawHash;
typedef RawHash<dense_hash_map<RawHashKey, Persistent<Value>, BufferHasher, BufferEq> > DenseRawHash;
typedef RawHash<map<RawHashKey, Persistent<Value>, BufferLess> > MapRawHash;

static Persistent<FunctionTemplate> sparseRawHash_ct;
static Persistent<FunctionTemplate> denseRawHash_ct;
static Persistent<FunctionTemplate> mapRawHash_ct;

void RegisterModule(Handle<Object> target) {
  SparseRawHash::init(target, SparseRawHash::NewWithSeed, sparseRawHash_ct, "Sparse");
  DenseRawHash::init(target, DenseRawHash::NewWithSeed, denseRawHash_ct, "Dense");
  MapRawHash::init(target, MapRawHash::New, mapRawHash_ct, "Map");
}

NODE_MODULE(rawhash, RegisterModule);
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: stgole.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: vg $ $Date: 2006-09-25 13:35:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sot.hxx"

#include "rtl/string.h"
#include "rtl/string.h"
#include "stgole.hxx"
#include "storinfo.hxx"     // Read/WriteClipboardFormat()

#include <tools/debug.hxx>
#if defined(_MSC_VER) && (_MSC_VER>=1400)
#pragma warning(disable: 4342)
#endif
///////////////////////// class StgInternalStream ////////////////////////

StgInternalStream::StgInternalStream
    ( BaseStorage& rStg, const String& rName, BOOL bWr )
{
    bIsWritable = TRUE;
    USHORT nMode = bWr
                 ? STREAM_WRITE | STREAM_SHARE_DENYALL
                 : STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE;
    pStrm = rStg.OpenStream( rName, nMode );

    // set the error code right here in the stream
    SetError( rStg.GetError() );
    SetBufferSize( 1024 );
}

StgInternalStream::~StgInternalStream()
{
    delete pStrm;
}

ULONG StgInternalStream::GetData( void* pData, ULONG nSize )
{
    if( pStrm )
    {
        nSize = pStrm->Read( pData, nSize );
        SetError( pStrm->GetError() );
        return nSize;
    }
    else
        return 0;
}

ULONG StgInternalStream::PutData( const void* pData, ULONG nSize )
{
    if( pStrm )
    {
        nSize = pStrm->Write( pData, nSize );
        SetError( pStrm->GetError() );
        return nSize;
    }
    else
        return 0;
}

ULONG StgInternalStream::SeekPos( ULONG nPos )
{
    return pStrm ? pStrm->Seek( nPos ) : 0;
}

void StgInternalStream::FlushData()
{
    if( pStrm )
    {
        pStrm->Flush();
        SetError( pStrm->GetError() );
    }
}

void StgInternalStream::Commit()
{
    Flush();
    pStrm->Commit();
}

///////////////////////// class StgCompObjStream /////////////////////////

StgCompObjStream::StgCompObjStream( BaseStorage& rStg, BOOL bWr )
            : StgInternalStream( rStg, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1CompObj" ) ), bWr )
{
    memset( &aClsId, 0, sizeof( ClsId ) );
    nCbFormat = 0;
}

BOOL StgCompObjStream::Load()
{
    memset( &aClsId, 0, sizeof( ClsId ) );
    nCbFormat = 0;
    aUserName.Erase();
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    Seek( 8L );     // skip the first part
    INT32 nMarker = 0;
    *this >> nMarker;
    if( nMarker == -1L )
    {
        *this >> aClsId;
        INT32 nLen1 = 0;
        *this >> nLen1;
        // higher bits are ignored
        nLen1 &= 0xFFFF;
        sal_Char* p = new sal_Char[ (USHORT) nLen1 ];
        if( Read( p, nLen1 ) == (ULONG) nLen1 )
        {
            aUserName = nLen1 ? String( p, gsl_getSystemTextEncoding() ) : String();
/*          // Now we can read the CB format
            INT32 nLen2 = 0;
            *this >> nLen2;
            if( nLen2 > 0 )
            {
                // get a string name
                if( nLen2 > nLen1 )
                    delete p, p = new char[ nLen2 ];
                if( Read( p, nLen2 ) == (ULONG) nLen2 && nLen2 )
                    nCbFormat = Exchange::RegisterFormatName( String( p ) );
                else
                    SetError( SVSTREAM_GENERALERROR );
            }
            else if( nLen2 == -1L )
                // Windows clipboard format
                *this >> nCbFormat;
            else
                // unknown identifier
                SetError( SVSTREAM_GENERALERROR );
*/
            nCbFormat = ReadClipboardFormat( *this );
        }
        else
            SetError( SVSTREAM_GENERALERROR );
        delete [] p;
    }
    return BOOL( GetError() == SVSTREAM_OK );
}

BOOL StgCompObjStream::Store()
{
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    Seek( 0L );
    ByteString aAsciiUserName( aUserName, RTL_TEXTENCODING_ASCII_US );
    *this << (INT16) 1          // Version?
              << (INT16) -2                     // 0xFFFE = Byte Order Indicator
              << (INT32) 0x0A03         // Windows 3.10
              << (INT32) -1L
              << aClsId             // Class ID
              << (INT32) (aAsciiUserName.Len() + 1)
              << (const char *)aAsciiUserName.GetBuffer()
              << (UINT8) 0;             // string terminator
/*  // determine the clipboard format string
    String aCbFmt;
    if( nCbFormat > FORMAT_GDIMETAFILE )
    aCbFmt = Exchange::GetFormatName( nCbFormat );
    if( aCbFmt.Len() )
        *this << (INT32) aCbFmt.Len() + 1
               << (const char*) aCbFmt
               << (UINT8) 0;
    else if( nCbFormat )
         *this << (INT32) -1            // for Windows
                << (INT32) nCbFormat;
    else
        *this << (INT32) 0;         // no clipboard format
*/
    WriteClipboardFormat( *this, nCbFormat );
    *this << (INT32) 0;             // terminator
    Commit();
    return BOOL( GetError() == SVSTREAM_OK );
}

/////////////////////////// class StgOleStream ///////////////////////////

StgOleStream::StgOleStream( BaseStorage& rStg, BOOL bWr )
            : StgInternalStream( rStg, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1Ole" ) ), bWr )
{
    nFlags = 0;
}

BOOL StgOleStream::Load()
{
    nFlags = 0;
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    INT32 version = 0;
    Seek( 0L );
    *this >> version >> nFlags;
    return BOOL( GetError() == SVSTREAM_OK );
}

BOOL StgOleStream::Store()
{
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    Seek( 0L );
    *this << (INT32) 0x02000001         // OLE version, format
          << (INT32) nFlags             // Object flags
          << (INT32) 0                  // Update Options
          << (INT32) 0                  // reserved
          << (INT32) 0;                 // Moniker 1
    Commit();
    return BOOL( GetError() == SVSTREAM_OK );
}

<commit_msg>INTEGRATION: CWS changefileheader (1.10.64); FILE MERGED 2008/03/31 12:49:58 rt 1.10.64.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: stgole.cxx,v $
 * $Revision: 1.11 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sot.hxx"

#include "rtl/string.h"
#include "rtl/string.h"
#include "stgole.hxx"
#include "storinfo.hxx"     // Read/WriteClipboardFormat()

#include <tools/debug.hxx>
#if defined(_MSC_VER) && (_MSC_VER>=1400)
#pragma warning(disable: 4342)
#endif
///////////////////////// class StgInternalStream ////////////////////////

StgInternalStream::StgInternalStream
    ( BaseStorage& rStg, const String& rName, BOOL bWr )
{
    bIsWritable = TRUE;
    USHORT nMode = bWr
                 ? STREAM_WRITE | STREAM_SHARE_DENYALL
                 : STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE;
    pStrm = rStg.OpenStream( rName, nMode );

    // set the error code right here in the stream
    SetError( rStg.GetError() );
    SetBufferSize( 1024 );
}

StgInternalStream::~StgInternalStream()
{
    delete pStrm;
}

ULONG StgInternalStream::GetData( void* pData, ULONG nSize )
{
    if( pStrm )
    {
        nSize = pStrm->Read( pData, nSize );
        SetError( pStrm->GetError() );
        return nSize;
    }
    else
        return 0;
}

ULONG StgInternalStream::PutData( const void* pData, ULONG nSize )
{
    if( pStrm )
    {
        nSize = pStrm->Write( pData, nSize );
        SetError( pStrm->GetError() );
        return nSize;
    }
    else
        return 0;
}

ULONG StgInternalStream::SeekPos( ULONG nPos )
{
    return pStrm ? pStrm->Seek( nPos ) : 0;
}

void StgInternalStream::FlushData()
{
    if( pStrm )
    {
        pStrm->Flush();
        SetError( pStrm->GetError() );
    }
}

void StgInternalStream::Commit()
{
    Flush();
    pStrm->Commit();
}

///////////////////////// class StgCompObjStream /////////////////////////

StgCompObjStream::StgCompObjStream( BaseStorage& rStg, BOOL bWr )
            : StgInternalStream( rStg, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1CompObj" ) ), bWr )
{
    memset( &aClsId, 0, sizeof( ClsId ) );
    nCbFormat = 0;
}

BOOL StgCompObjStream::Load()
{
    memset( &aClsId, 0, sizeof( ClsId ) );
    nCbFormat = 0;
    aUserName.Erase();
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    Seek( 8L );     // skip the first part
    INT32 nMarker = 0;
    *this >> nMarker;
    if( nMarker == -1L )
    {
        *this >> aClsId;
        INT32 nLen1 = 0;
        *this >> nLen1;
        // higher bits are ignored
        nLen1 &= 0xFFFF;
        sal_Char* p = new sal_Char[ (USHORT) nLen1 ];
        if( Read( p, nLen1 ) == (ULONG) nLen1 )
        {
            aUserName = nLen1 ? String( p, gsl_getSystemTextEncoding() ) : String();
/*          // Now we can read the CB format
            INT32 nLen2 = 0;
            *this >> nLen2;
            if( nLen2 > 0 )
            {
                // get a string name
                if( nLen2 > nLen1 )
                    delete p, p = new char[ nLen2 ];
                if( Read( p, nLen2 ) == (ULONG) nLen2 && nLen2 )
                    nCbFormat = Exchange::RegisterFormatName( String( p ) );
                else
                    SetError( SVSTREAM_GENERALERROR );
            }
            else if( nLen2 == -1L )
                // Windows clipboard format
                *this >> nCbFormat;
            else
                // unknown identifier
                SetError( SVSTREAM_GENERALERROR );
*/
            nCbFormat = ReadClipboardFormat( *this );
        }
        else
            SetError( SVSTREAM_GENERALERROR );
        delete [] p;
    }
    return BOOL( GetError() == SVSTREAM_OK );
}

BOOL StgCompObjStream::Store()
{
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    Seek( 0L );
    ByteString aAsciiUserName( aUserName, RTL_TEXTENCODING_ASCII_US );
    *this << (INT16) 1          // Version?
              << (INT16) -2                     // 0xFFFE = Byte Order Indicator
              << (INT32) 0x0A03         // Windows 3.10
              << (INT32) -1L
              << aClsId             // Class ID
              << (INT32) (aAsciiUserName.Len() + 1)
              << (const char *)aAsciiUserName.GetBuffer()
              << (UINT8) 0;             // string terminator
/*  // determine the clipboard format string
    String aCbFmt;
    if( nCbFormat > FORMAT_GDIMETAFILE )
    aCbFmt = Exchange::GetFormatName( nCbFormat );
    if( aCbFmt.Len() )
        *this << (INT32) aCbFmt.Len() + 1
               << (const char*) aCbFmt
               << (UINT8) 0;
    else if( nCbFormat )
         *this << (INT32) -1            // for Windows
                << (INT32) nCbFormat;
    else
        *this << (INT32) 0;         // no clipboard format
*/
    WriteClipboardFormat( *this, nCbFormat );
    *this << (INT32) 0;             // terminator
    Commit();
    return BOOL( GetError() == SVSTREAM_OK );
}

/////////////////////////// class StgOleStream ///////////////////////////

StgOleStream::StgOleStream( BaseStorage& rStg, BOOL bWr )
            : StgInternalStream( rStg, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1Ole" ) ), bWr )
{
    nFlags = 0;
}

BOOL StgOleStream::Load()
{
    nFlags = 0;
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    INT32 version = 0;
    Seek( 0L );
    *this >> version >> nFlags;
    return BOOL( GetError() == SVSTREAM_OK );
}

BOOL StgOleStream::Store()
{
    if( GetError() != SVSTREAM_OK )
        return FALSE;
    Seek( 0L );
    *this << (INT32) 0x02000001         // OLE version, format
          << (INT32) nFlags             // Object flags
          << (INT32) 0                  // Update Options
          << (INT32) 0                  // reserved
          << (INT32) 0;                 // Moniker 1
    Commit();
    return BOOL( GetError() == SVSTREAM_OK );
}

<|endoftext|>


<commit_before>//===-- FileSpecList.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/FileSpecList.h"

#include "lldb/Utility/ConstString.h" // for ConstString
#include "lldb/Utility/Stream.h"

#include <utility> // for find

#include <stdint.h> // for UINT32_MAX

using namespace lldb_private;
using namespace std;

FileSpecList::FileSpecList() : m_files() {}

FileSpecList::FileSpecList(const FileSpecList &rhs) = default;

FileSpecList::~FileSpecList() = default;

//------------------------------------------------------------------
// Assignment operator
//------------------------------------------------------------------
const FileSpecList &FileSpecList::operator=(const FileSpecList &rhs) {
  if (this != &rhs)
    m_files = rhs.m_files;
  return *this;
}

//------------------------------------------------------------------
// Append the "file_spec" to the end of the file spec list.
//------------------------------------------------------------------
void FileSpecList::Append(const FileSpec &file_spec) {
  m_files.push_back(file_spec);
}

//------------------------------------------------------------------
// Only append the "file_spec" if this list doesn't already contain
// it.
//
// Returns true if "file_spec" was added, false if this list already
// contained a copy of "file_spec".
//------------------------------------------------------------------
bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) {
  collection::iterator end = m_files.end();
  if (find(m_files.begin(), end, file_spec) == end) {
    m_files.push_back(file_spec);
    return true;
  }
  return false;
}

//------------------------------------------------------------------
// Clears the file list.
//------------------------------------------------------------------
void FileSpecList::Clear() { m_files.clear(); }

//------------------------------------------------------------------
// Dumps the file list to the supplied stream pointer "s".
//------------------------------------------------------------------
void FileSpecList::Dump(Stream *s, const char *separator_cstr) const {
  collection::const_iterator pos, end = m_files.end();
  for (pos = m_files.begin(); pos != end; ++pos) {
    pos->Dump(s);
    if (separator_cstr && ((pos + 1) != end))
      s->PutCString(separator_cstr);
  }
}

//------------------------------------------------------------------
// Find the index of the file in the file spec list that matches
// "file_spec" starting "start_idx" entries into the file spec list.
//
// Returns the valid index of the file that matches "file_spec" if
// it is found, else std::numeric_limits<uint32_t>::max() is returned.
//------------------------------------------------------------------
size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
                                   bool full, bool remove_dots) const {
  const size_t num_files = m_files.size();

  // When looking for files, we will compare only the filename if the
  // FILE_SPEC argument is empty
  bool compare_filename_only = file_spec.GetDirectory().IsEmpty();

  for (size_t idx = start_idx; idx < num_files; ++idx) {
    if (compare_filename_only) {
      if (ConstString::Equals(
              m_files[idx].GetFilename(), file_spec.GetFilename(),
              file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
        return idx;
    } else {
      if (FileSpec::Equal(m_files[idx], file_spec, full, remove_dots))
        return idx;
    }
  }

  // We didn't find the file, return an invalid index
  return UINT32_MAX;
}

//------------------------------------------------------------------
// Returns the FileSpec object at index "idx". If "idx" is out of
// range, then an empty FileSpec object will be returned.
//------------------------------------------------------------------
const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const {
  if (idx < m_files.size())
    return m_files[idx];
  static FileSpec g_empty_file_spec;
  return g_empty_file_spec;
}

const FileSpec *FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const {
  if (idx < m_files.size())
    return &m_files[idx];
  return nullptr;
}

//------------------------------------------------------------------
// Return the size in bytes that this object takes in memory. This
// returns the size in bytes of this object's member variables and
// any FileSpec objects its member variables contain, the result
// doesn't not include the string values for the directories any
// filenames as those are in shared string pools.
//------------------------------------------------------------------
size_t FileSpecList::MemorySize() const {
  size_t mem_size = sizeof(FileSpecList);
  collection::const_iterator pos, end = m_files.end();
  for (pos = m_files.begin(); pos != end; ++pos) {
    mem_size += pos->MemorySize();
  }

  return mem_size;
}

//------------------------------------------------------------------
// Return the number of files in the file spec list.
//------------------------------------------------------------------
size_t FileSpecList::GetSize() const { return m_files.size(); }

size_t FileSpecList::GetFilesMatchingPartialPath(const char *path,
                                                 bool dir_okay,
                                                 FileSpecList &matches) {
#if 0 // FIXME: Just sketching...
    matches.Clear();
    using namespace llvm::sys::fs;
    file_status stats;
    if (status(path, stats, false))
      return 0;
    if (exists(stats)) {
      if (is_symlink_file(stats)) {
        // Shouldn't there be a method that realpath's a file?
      }
      if (is_regular_file(stats) || (is_directory(stats) && dir_okay)) {
        matches.Append(FileSpec(path));
        return 1;
      } else if (is_directory(stats)) {
        // Fill the match list with all the files in the directory:
      } else {
        return 0;
      }
    } else {
        ConstString dir_name = path_spec.GetDirectory();
        ConstString file_name = GetFilename();
        if (dir_name == nullptr)
        {
            // Match files in the CWD.
        }
        else
        {
            // Match files in the given directory:
        }
    }
#endif
  return 0;
}
<commit_msg>[Core] Garbage collect dead code untouched in years. NFCI.<commit_after>//===-- FileSpecList.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/FileSpecList.h"

#include "lldb/Utility/ConstString.h" // for ConstString
#include "lldb/Utility/Stream.h"

#include <utility> // for find

#include <stdint.h> // for UINT32_MAX

using namespace lldb_private;
using namespace std;

FileSpecList::FileSpecList() : m_files() {}

FileSpecList::FileSpecList(const FileSpecList &rhs) = default;

FileSpecList::~FileSpecList() = default;

//------------------------------------------------------------------
// Assignment operator
//------------------------------------------------------------------
const FileSpecList &FileSpecList::operator=(const FileSpecList &rhs) {
  if (this != &rhs)
    m_files = rhs.m_files;
  return *this;
}

//------------------------------------------------------------------
// Append the "file_spec" to the end of the file spec list.
//------------------------------------------------------------------
void FileSpecList::Append(const FileSpec &file_spec) {
  m_files.push_back(file_spec);
}

//------------------------------------------------------------------
// Only append the "file_spec" if this list doesn't already contain
// it.
//
// Returns true if "file_spec" was added, false if this list already
// contained a copy of "file_spec".
//------------------------------------------------------------------
bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) {
  collection::iterator end = m_files.end();
  if (find(m_files.begin(), end, file_spec) == end) {
    m_files.push_back(file_spec);
    return true;
  }
  return false;
}

//------------------------------------------------------------------
// Clears the file list.
//------------------------------------------------------------------
void FileSpecList::Clear() { m_files.clear(); }

//------------------------------------------------------------------
// Dumps the file list to the supplied stream pointer "s".
//------------------------------------------------------------------
void FileSpecList::Dump(Stream *s, const char *separator_cstr) const {
  collection::const_iterator pos, end = m_files.end();
  for (pos = m_files.begin(); pos != end; ++pos) {
    pos->Dump(s);
    if (separator_cstr && ((pos + 1) != end))
      s->PutCString(separator_cstr);
  }
}

//------------------------------------------------------------------
// Find the index of the file in the file spec list that matches
// "file_spec" starting "start_idx" entries into the file spec list.
//
// Returns the valid index of the file that matches "file_spec" if
// it is found, else std::numeric_limits<uint32_t>::max() is returned.
//------------------------------------------------------------------
size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
                                   bool full, bool remove_dots) const {
  const size_t num_files = m_files.size();

  // When looking for files, we will compare only the filename if the
  // FILE_SPEC argument is empty
  bool compare_filename_only = file_spec.GetDirectory().IsEmpty();

  for (size_t idx = start_idx; idx < num_files; ++idx) {
    if (compare_filename_only) {
      if (ConstString::Equals(
              m_files[idx].GetFilename(), file_spec.GetFilename(),
              file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
        return idx;
    } else {
      if (FileSpec::Equal(m_files[idx], file_spec, full, remove_dots))
        return idx;
    }
  }

  // We didn't find the file, return an invalid index
  return UINT32_MAX;
}

//------------------------------------------------------------------
// Returns the FileSpec object at index "idx". If "idx" is out of
// range, then an empty FileSpec object will be returned.
//------------------------------------------------------------------
const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const {
  if (idx < m_files.size())
    return m_files[idx];
  static FileSpec g_empty_file_spec;
  return g_empty_file_spec;
}

const FileSpec *FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const {
  if (idx < m_files.size())
    return &m_files[idx];
  return nullptr;
}

//------------------------------------------------------------------
// Return the size in bytes that this object takes in memory. This
// returns the size in bytes of this object's member variables and
// any FileSpec objects its member variables contain, the result
// doesn't not include the string values for the directories any
// filenames as those are in shared string pools.
//------------------------------------------------------------------
size_t FileSpecList::MemorySize() const {
  size_t mem_size = sizeof(FileSpecList);
  collection::const_iterator pos, end = m_files.end();
  for (pos = m_files.begin(); pos != end; ++pos) {
    mem_size += pos->MemorySize();
  }

  return mem_size;
}

//------------------------------------------------------------------
// Return the number of files in the file spec list.
//------------------------------------------------------------------
size_t FileSpecList::GetSize() const { return m_files.size(); }

size_t FileSpecList::GetFilesMatchingPartialPath(const char *path,
                                                 bool dir_okay,
                                                 FileSpecList &matches) {
  return 0;
}
<|endoftext|>


<commit_before>// Do nothing, if no thread support

#include <BALL/VIEW/KERNEL/threads.h>
#ifdef BALL_QT_HAS_THREADS

#include <BALL/VIEW/MODELS/modelProcessor.h>
#include <BALL/VIEW/MODELS/colorProcessor.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/MOLMEC/COMMON/forceField.h>
#include <BALL/MOLMEC/MINIMIZATION/energyMinimizer.h>
#include <BALL/MOLMEC/MDSIMULATION/molecularDynamics.h>
#include <BALL/VIEW/WIDGETS/scene.h>
#include <BALL/MOLMEC/COMMON/snapShotManager.h>

#include <qapplication.h>

namespace BALL
{
	namespace VIEW
	{

		FetchHTMLThread::FetchHTMLThread()
			throw()
			: QThread()
		{
		}

		void FetchHTMLThread::setURL(const String& url)
			throw()
		{
			url_ = url;
		}

		const String& FetchHTMLThread::getFilename() const
			throw()
		{
			return filename_;
		}

		void FetchHTMLThread::run()
		{
			if (url_ == "") return;
			try
			{
				File f(url_);
				File::createTemporaryFilename(filename_);
				f.copyTo(filename_);
			}
			catch(...)
			{}
		}

		// ==========================================

		UpdateRepresentationThread::UpdateRepresentationThread()
			throw()
			: QThread(),
				rep_(0)
		{
		}

		void UpdateRepresentationThread::run()
		{
			if (rep_ == 0) return;
			rep_->update_(rebuild_);
		}

		SimulationThread::SimulationThread()
			: QThread(),
				main_control_(0),
				dcd_file_(0),
				composite_(0),
				update_vis_running_(false)
		{
		}

		void SimulationThread::run()
		{
			// overloaded in derived classes
		}

		void SimulationThread::updateScene_()
		{
			if (main_control_->stopedSimulation())
			{
				update_vis_running_ = false;
				return;
			}

			update_vis_running_ = true;
			// notify MainControl to update all Representations for the Composite
			UpdateCompositeEvent* se = new UpdateCompositeEvent;
			se->setComposite(composite_);
			qApp->postEvent(main_control_, se);
		}

		void SimulationThread::output_(const String& string)
		{
			if (main_control_->stopedSimulation()) return;

			SimulationOutput* su = new SimulationOutput;
			su->setMessage(string);
			qApp->postEvent(main_control_, su);  // Qt will delete it when done
		}

		void SimulationThread::finish_()
		{
			SimulationThreadFinished* su = new SimulationThreadFinished;
			qApp->postEvent(main_control_, su);  // Qt will delete it when done
		}

		void EnergyMinimizerThread::run()
		{
			try
			{
				if (minimizer_ == 0 ||
						minimizer_->getForceField() == 0 ||
						minimizer_->getForceField()->getSystem() == 0 ||
						main_control_ == 0)
				{
					throw Exception::NullPointer(__FILE__, __LINE__);
				}
				ForceField& ff = *minimizer_->getForceField();

				// iterate until done and refresh the screen every "steps" iterations
				while (!main_control_->stopedSimulation() &&
								minimizer_->getNumberOfIterations() < minimizer_->getMaxNumberOfIterations() &&
							 !minimizer_->minimize(steps_between_updates_, true))
				{
					updateScene_();

					QString message;
					message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
													minimizer_->getNumberOfIterations(),
													ff.getEnergy(), ff.getRMSGradient());
					output_(message.ascii());

					// prevent continuation of simulation, before update of visualisation has finished
					while (update_vis_running_ && !main_control_->stopedSimulation()) msleep(10);
				}

				output_(ff.getResults());
				output_("final RMS gadient    : " + String(ff.getRMSGradient()) + " kJ/(mol A)   after "
								+ String(minimizer_->getNumberOfIterations()) + " iterations\n");
				finish_();
			}
			catch(Exception::GeneralException e)
			{
				String txt = String("Calculation aborted because of throwed exception: ")
											+ __FILE__ + " " + __LINE__ + " " + e.getMessage();
				output_(txt);
				finish_();
			}
		}

		EnergyMinimizerThread::EnergyMinimizerThread()
			: SimulationThread(),
				minimizer_(0)
		{
		}

		EnergyMinimizerThread::~EnergyMinimizerThread()
		{
			if (minimizer_ != 0)
			{
				delete minimizer_;
			}
		}

		void EnergyMinimizerThread::setEnergyMinimizer(EnergyMinimizer* minimizer)
		{
			if (minimizer_ != 0)
			{
				delete minimizer_;
			}
			minimizer_ = minimizer;
		}

		// =====================================================
		void MDSimulationThread::run()
			throw(Exception::NullPointer)
		{
			try
			{
				if (md_ == 0 ||
						md_->getForceField() == 0 ||
						md_->getForceField()->getSystem() == 0 ||
						main_control_ == 0)
				{
					throw Exception::NullPointer(__FILE__, __LINE__);
				}
				ForceField& ff = *md_->getForceField();

				SnapShotManager manager(ff.getSystem(), &ff, dcd_file_);
				manager.setFlushToDiskFrequency(10);
				// iterate until done and refresh the screen every "steps" iterations

				while (md_->getNumberOfIterations() < steps_ &&
							 !main_control_->stopedSimulation())
				{
					// prevent continuation of simulation, before update of visualisation has finished
					while (update_vis_running_ && !main_control_->stopedSimulation()) msleep(10);

					md_->simulateIterations(steps_between_updates_, true);
					updateScene_();

					QString message;
					message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
													md_->getNumberOfIterations(), ff.getEnergy(),
													ff.getRMSGradient());
					output_(message.ascii());

					if (save_images_)
					{
						Scene* scene= (Scene*) Scene::getInstance(0);
						scene->exportPNG();
					}

					if (dcd_file_) manager.takeSnapShot();
				}

				if (dcd_file_) manager.flushToDisk();

 				output_(ff.getResults());
				output_("final RMS gadient    : " + String(ff.getRMSGradient()) + " kJ/(mol A)   after "
								+ String(md_->getNumberOfIterations()) + " iterations\n");
				finish_();
			}
			catch(Exception::GeneralException e)
			{
				String txt = String("Calculation aborted because of throwed exception: ")
											+ __FILE__ + " " + __LINE__ + " " + e.getMessage();
				output_(txt);
				finish_();
			}
		}

		MDSimulationThread::MDSimulationThread()
			: SimulationThread(),
				md_(0),
				save_images_(false)
		{
		}

		MDSimulationThread::~MDSimulationThread()
		{
			if (md_ != 0)
			{
				delete md_;
			}
		}

		void MDSimulationThread::setMolecularDynamics(MolecularDynamics* md)
		{
			if (md_ != 0)
			{
				delete md_;
			}

			md_ = md;
		}

	} // namespace VIEW
} // namespace BALL

#endif //Thread support
<commit_msg>no message<commit_after>// Do nothing, if no thread support

#include <BALL/VIEW/KERNEL/threads.h>
#ifdef BALL_QT_HAS_THREADS

#include <BALL/VIEW/MODELS/modelProcessor.h>
#include <BALL/VIEW/MODELS/colorProcessor.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/MOLMEC/COMMON/forceField.h>
#include <BALL/MOLMEC/MINIMIZATION/energyMinimizer.h>
#include <BALL/MOLMEC/MDSIMULATION/molecularDynamics.h>
#include <BALL/VIEW/WIDGETS/scene.h>
#include <BALL/MOLMEC/COMMON/snapShotManager.h>

#include <qapplication.h>

namespace BALL
{
	namespace VIEW
	{

		FetchHTMLThread::FetchHTMLThread()
			throw()
			: QThread()
		{
		}

		void FetchHTMLThread::setURL(const String& url)
			throw()
		{
			url_ = url;
		}

		const String& FetchHTMLThread::getFilename() const
			throw()
		{
			return filename_;
		}

		void FetchHTMLThread::run()
		{
			if (url_ == "") return;
			try
			{
				File f(url_);
				File::createTemporaryFilename(filename_);
				f.copyTo(filename_);
			}
			catch(...)
			{}
		}

		// ==========================================

		UpdateRepresentationThread::UpdateRepresentationThread()
			throw()
			: QThread(),
				rep_(0)
		{
		}

		void UpdateRepresentationThread::run()
		{
			if (rep_ == 0) return;
			rep_->update_(rebuild_);
		}

		SimulationThread::SimulationThread()
			: QThread(),
				main_control_(0),
				dcd_file_(0),
				composite_(0),
				update_vis_running_(false)
		{
		}

		void SimulationThread::run()
		{
			// overloaded in derived classes
		}

		void SimulationThread::updateScene_()
		{
			if (main_control_->stopedSimulation())
			{
				update_vis_running_ = false;
				return;
			}

			update_vis_running_ = true;
			// notify MainControl to update all Representations for the Composite
			UpdateCompositeEvent* se = new UpdateCompositeEvent;
			se->setComposite(composite_);
			qApp->postEvent(main_control_, se);
		}

		void SimulationThread::output_(const String& string)
		{
			if (main_control_->stopedSimulation()) return;

			SimulationOutput* su = new SimulationOutput;
			su->setMessage(string);
			qApp->postEvent(main_control_, su);  // Qt will delete it when done
		}

		void SimulationThread::finish_()
		{
			SimulationThreadFinished* su = new SimulationThreadFinished;
			qApp->postEvent(main_control_, su);  // Qt will delete it when done
		}

		void EnergyMinimizerThread::run()
		{
			try
			{
				if (minimizer_ == 0 ||
						minimizer_->getForceField() == 0 ||
						minimizer_->getForceField()->getSystem() == 0 ||
						main_control_ == 0)
				{
					throw Exception::NullPointer(__FILE__, __LINE__);
				}
				ForceField& ff = *minimizer_->getForceField();

				// iterate until done and refresh the screen every "steps" iterations
				while (!main_control_->stopedSimulation() &&
								minimizer_->getNumberOfIterations() < minimizer_->getMaxNumberOfIterations() &&
							 !minimizer_->minimize(steps_between_updates_, true))
				{
					updateScene_();

					QString message;
					message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
													minimizer_->getNumberOfIterations(),
													ff.getEnergy(), ff.getRMSGradient());
					output_(message.ascii());

					// prevent continuation of simulation, before update of visualisation has finished
					while (update_vis_running_ && !main_control_->stopedSimulation()) msleep(10);
				}

				updateScene_();

				output_(ff.getResults());
				output_("final RMS gadient    : " + String(ff.getRMSGradient()) + " kJ/(mol A)   after "
								+ String(minimizer_->getNumberOfIterations()) + " iterations\n");
				finish_();
			}
			catch(Exception::GeneralException e)
			{
				String txt = String("Calculation aborted because of throwed exception: ")
											+ __FILE__ + " " + __LINE__ + " " + e.getMessage();
				output_(txt);
				finish_();
			}
		}

		EnergyMinimizerThread::EnergyMinimizerThread()
			: SimulationThread(),
				minimizer_(0)
		{
		}

		EnergyMinimizerThread::~EnergyMinimizerThread()
		{
			if (minimizer_ != 0)
			{
				delete minimizer_;
			}
		}

		void EnergyMinimizerThread::setEnergyMinimizer(EnergyMinimizer* minimizer)
		{
			if (minimizer_ != 0)
			{
				delete minimizer_;
			}
			minimizer_ = minimizer;
		}

		// =====================================================
		void MDSimulationThread::run()
			throw(Exception::NullPointer)
		{
			try
			{
				if (md_ == 0 ||
						md_->getForceField() == 0 ||
						md_->getForceField()->getSystem() == 0 ||
						main_control_ == 0)
				{
					throw Exception::NullPointer(__FILE__, __LINE__);
				}
				ForceField& ff = *md_->getForceField();

				SnapShotManager manager(ff.getSystem(), &ff, dcd_file_);
				manager.setFlushToDiskFrequency(10);
				// iterate until done and refresh the screen every "steps" iterations

				while (md_->getNumberOfIterations() < steps_ &&
							 !main_control_->stopedSimulation())
				{
					// prevent continuation of simulation, before update of visualisation has finished
					while (update_vis_running_ && !main_control_->stopedSimulation()) msleep(10);

					md_->simulateIterations(steps_between_updates_, true);
					updateScene_();

					QString message;
					message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
													md_->getNumberOfIterations(), ff.getEnergy(),
													ff.getRMSGradient());
					output_(message.ascii());

					if (save_images_)
					{
						Scene* scene= (Scene*) Scene::getInstance(0);
						scene->exportPNG();
					}

					if (dcd_file_) manager.takeSnapShot();
				}

				updateScene_();

				if (dcd_file_) manager.flushToDisk();

 				output_(ff.getResults());
				output_("final RMS gadient    : " + String(ff.getRMSGradient()) + " kJ/(mol A)   after "
								+ String(md_->getNumberOfIterations()) + " iterations\n");
				finish_();
			}
			catch(Exception::GeneralException e)
			{
				String txt = String("Calculation aborted because of throwed exception: ")
											+ __FILE__ + " " + __LINE__ + " " + e.getMessage();
				output_(txt);
				finish_();
			}
		}

		MDSimulationThread::MDSimulationThread()
			: SimulationThread(),
				md_(0),
				save_images_(false)
		{
		}

		MDSimulationThread::~MDSimulationThread()
		{
			if (md_ != 0)
			{
				delete md_;
			}
		}

		void MDSimulationThread::setMolecularDynamics(MolecularDynamics* md)
		{
			if (md_ != 0)
			{
				delete md_;
			}

			md_ = md;
		}

	} // namespace VIEW
} // namespace BALL

#endif //Thread support
<|endoftext|>