/**
   * A "safe" array comparison that is not vulnerable to side-channel
   * "timing attacks". All comparisons of non-null, equal length bytes should
   * take same amount of time. We use this for cryptographic comparisons.
   * 
   * @param b1   A byte array to compare.
   * @param b2   A second byte array to compare.
   * @return     {@code true} if both byte arrays are null or if both byte
   *             arrays are identical or have the same value; otherwise
   *             {@code false} is returned.
   */
  bool CryptoHelper::arrayCompare(const byte b1[], size_t s1, const byte b2[], size_t s2)
  {
    ASSERT(b1);
    ASSERT(s1);
    ASSERT(b2);
    ASSERT(s2);

    try
    {
      // Will throw if ptr wraps. T* and size_t causing trouble on Linux
      SafeInt<size_t> si1((size_t)b1); si1 += s1;
      g_dummy = (void*)(size_t)si1;
      SafeInt<size_t> si2((size_t)b2); si2 += s2;
      g_dummy = (void*)(size_t)si2;
    }
    catch(const SafeIntException&)
    {
      throw IllegalArgumentException("Source or destination array pointer wrap");
    }

    // These early outs break the contract regarding timing.
    // https://code.google.com/p/owasp-esapi-cplusplus/issues/detail?id=5

    if ( b1 == b2 ) {
      return true;
    }
    if ( b1 == nullptr || b2 == nullptr ) {
      return (b1 == b2);
    }
    if ( s1 != s2 ) {
      return false;
    }
    
    // Make sure to go through ALL the bytes. We use the fact that if
    // you XOR any bit stream with itself the result will be all 0 bits,
    // which in turn yields 0 for the result.
    int result = 0;
    for(size_t i = 0; i < s2; i++) {
      // XOR the 2 current bytes and then OR with the outstanding result.
      result |= (b1[i] ^ b2[i]);
    }
    return (result == 0) ? true : false;
  }
Beispiel #2
0
IntersectionMatrix*
RelateComputer::computeIM()
{
	// since Geometries are finite and embedded in a 2-D space, the EE element must always be 2
	im->set(Location::EXTERIOR,Location::EXTERIOR,2);
	// if the Geometries don't overlap there is nothing to do
	const Envelope *e1=(*arg)[0]->getGeometry()->getEnvelopeInternal();
	const Envelope *e2=(*arg)[1]->getGeometry()->getEnvelopeInternal();
	if (!e1->intersects(e2)) {
		computeDisjointIM(im.get());
		return im.release();
	}

	std::auto_ptr<SegmentIntersector> si1 (
		(*arg)[0]->computeSelfNodes(&li,false)
	);
	std::auto_ptr<SegmentIntersector> si2 (
		(*arg)[1]->computeSelfNodes(&li,false)
	);

	// compute intersections between edges of the two input geometries
	std::auto_ptr< SegmentIntersector> intersector (
    (*arg)[0]->computeEdgeIntersections((*arg)[1], &li,false)
  );
	computeIntersectionNodes(0);
	computeIntersectionNodes(1);

	/*
	 * Copy the labelling for the nodes in the parent Geometries.
	 * These override any labels determined by intersections
	 * between the geometries.
	 */
	copyNodesAndLabels(0);
	copyNodesAndLabels(1);

	/*
	 * complete the labelling for any nodes which only have a
	 * label for a single geometry
	 */
	//Debug.addWatch(nodes.find(new Coordinate(110, 200)));
	//Debug.printWatch();
	labelIsolatedNodes();
	//Debug.printWatch();

	/*
	 * If a proper intersection was found, we can set a lower bound
	 * on the IM.
	 */
	computeProperIntersectionIM(intersector.get(), im.get());

	/*
	 * Now process improper intersections
	 * (eg where one or other of the geometrys has a vertex at the
	 * intersection point)
	 * We need to compute the edge graph at all nodes to determine
	 * the IM.
	 */
	// build EdgeEnds for all intersections
	EdgeEndBuilder eeBuilder;
	std::auto_ptr< std::vector<EdgeEnd*> > ee0 (
		eeBuilder.computeEdgeEnds((*arg)[0]->getEdges())
  );
	insertEdgeEnds(ee0.get());
	std::auto_ptr< std::vector<EdgeEnd*> > ee1 (
		eeBuilder.computeEdgeEnds((*arg)[1]->getEdges())
  );
	insertEdgeEnds(ee1.get());
	//Debug.println("==== NodeList ===");
	//Debug.print(nodes);
	labelNodeEdges();

	/**
	 * Compute the labeling for isolated components.
	 * Isolated components are components that do not touch any
	 * other components in the graph.
	 * They can be identified by the fact that they will
	 * contain labels containing ONLY a single element, the one for
	 * their parent geometry.
	 * We only need to check components contained in the input graphs,
	 * since isolated components will not have been replaced by new
	 * components formed by intersections.
	 */
	//debugPrintln("Graph A isolated edges - ");
	labelIsolatedEdges(0,1);
	//debugPrintln("Graph B isolated edges - ");
	labelIsolatedEdges(1,0);
	// update the IM from all components
	updateIM(im.get());
	return im.release();
}
Beispiel #3
0
inline children launch_pipeline(const Entries &entries) 
{ 
    BOOST_ASSERT(entries.size() >= 2); 

    children cs; 
    detail::file_handle fhinvalid; 

    boost::scoped_array<detail::pipe> pipes(new detail::pipe[entries.size() - 1]); 

#if defined(BOOST_POSIX_API) 
    { 
        typename Entries::size_type i = 0; 
        const typename Entries::value_type::context_type &ctx = entries[i].context; 

        detail::info_map infoin, infoout; 

        if (ctx.stdin_behavior.get_type() != stream_behavior::close) 
        { 
            detail::stream_info si = detail::stream_info(ctx.stdin_behavior, false); 
            infoin.insert(detail::info_map::value_type(STDIN_FILENO, si)); 
        } 

        BOOST_ASSERT(ctx.stdout_behavior.get_type() == stream_behavior::close); 
        detail::stream_info si2(close_stream(), true); 
        si2.type_ = detail::stream_info::use_handle; 
        si2.handle_ = pipes[i].wend().release(); 
        infoout.insert(detail::info_map::value_type(STDOUT_FILENO, si2)); 

        if (ctx.stderr_behavior.get_type() != stream_behavior::close) 
        { 
            detail::stream_info si = detail::stream_info(ctx.stderr_behavior, true); 
            infoout.insert(detail::info_map::value_type(STDERR_FILENO, si)); 
        } 

        detail::posix_setup s; 
        s.work_directory = ctx.work_directory; 

        pid_t pid = detail::posix_start(entries[i].executable, entries[i].arguments, ctx.environment, infoin, infoout, s); 

        detail::file_handle fhstdin; 

        if (ctx.stdin_behavior.get_type() == stream_behavior::capture) 
        { 
            fhstdin = detail::posix_info_locate_pipe(infoin, STDIN_FILENO, false); 
            BOOST_ASSERT(fhstdin.valid()); 
        } 

        cs.push_back(child(pid, fhstdin, fhinvalid, fhinvalid)); 
    } 

    for (typename Entries::size_type i = 1; i < entries.size() - 1; ++i) 
    { 
        const typename Entries::value_type::context_type &ctx = entries[i].context; 
        detail::info_map infoin, infoout; 

        BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); 
        detail::stream_info si1(close_stream(), false); 
        si1.type_ = detail::stream_info::use_handle; 
        si1.handle_ = pipes[i - 1].rend().release(); 
        infoin.insert(detail::info_map::value_type(STDIN_FILENO, si1)); 

        BOOST_ASSERT(ctx.stdout_behavior.get_type() == stream_behavior::close); 
        detail::stream_info si2(close_stream(), true); 
        si2.type_ = detail::stream_info::use_handle; 
        si2.handle_ = pipes[i].wend().release(); 
        infoout.insert(detail::info_map::value_type(STDOUT_FILENO, si2)); 

        if (ctx.stderr_behavior.get_type() != stream_behavior::close) 
        { 
            detail::stream_info si = detail::stream_info(ctx.stderr_behavior, true); 
            infoout.insert(detail::info_map::value_type(STDERR_FILENO, si)); 
        } 

        detail::posix_setup s; 
        s.work_directory = ctx.work_directory; 

        pid_t pid = detail::posix_start(entries[i].executable, entries[i].arguments, ctx.environment, infoin, infoout, s); 

        cs.push_back(child(pid, fhinvalid, fhinvalid, fhinvalid)); 
    } 

    { 
        typename Entries::size_type i = entries.size() - 1; 
        const typename Entries::value_type::context_type &ctx = entries[i].context; 

        detail::info_map infoin, infoout; 

        BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); 
        detail::stream_info si1(close_stream(), false); 
        si1.type_ = detail::stream_info::use_handle; 
        si1.handle_ = pipes[i - 1].rend().release(); 
        infoin.insert(detail::info_map::value_type(STDIN_FILENO, si1)); 

        if (ctx.stdout_behavior.get_type() != stream_behavior::close) 
        { 
            detail::stream_info si = detail::stream_info(ctx.stdout_behavior, true); 
            infoout.insert(detail::info_map::value_type(STDOUT_FILENO, si)); 
        } 

        if (ctx.stderr_behavior.get_type() != stream_behavior::close) 
        { 
            detail::stream_info si = detail::stream_info(ctx.stderr_behavior, true); 
            infoout.insert(detail::info_map::value_type(STDERR_FILENO, si)); 
        } 

        detail::posix_setup s; 
        s.work_directory = ctx.work_directory; 

        pid_t pid = detail::posix_start(entries[i].executable, entries[i].arguments, ctx.environment, infoin, infoout, s); 

        detail::file_handle fhstdout, fhstderr; 

        if (ctx.stdout_behavior.get_type() == stream_behavior::capture) 
        { 
            fhstdout = detail::posix_info_locate_pipe(infoout, STDOUT_FILENO, true); 
            BOOST_ASSERT(fhstdout.valid()); 
        } 

        if (ctx.stderr_behavior.get_type() == stream_behavior::capture) 
        { 
            fhstderr = detail::posix_info_locate_pipe(infoout, STDERR_FILENO, true); 
            BOOST_ASSERT(fhstderr.valid()); 
        } 

        cs.push_back(child(pid, fhinvalid, fhstdout, fhstderr)); 
    } 
#elif defined(BOOST_WINDOWS_API) 
    STARTUPINFOA si; 
    detail::win32_setup s; 
    s.startupinfo = &si; 

    { 
        typename Entries::size_type i = 0; 
        const typename Entries::value_type::context_type &ctx = entries[i].context; 

        detail::stream_info sii = detail::stream_info(ctx.stdin_behavior, false); 
        detail::file_handle fhstdin; 
        if (sii.type_ == detail::stream_info::use_pipe) 
            fhstdin = sii.pipe_->wend(); 

        BOOST_ASSERT(ctx.stdout_behavior.get_type() == stream_behavior::close); 
        detail::stream_info sio(close_stream(), true); 
        sio.type_ = detail::stream_info::use_handle; 
        sio.handle_ = pipes[i].wend().release(); 

        detail::stream_info sie(ctx.stderr_behavior, true); 

        s.work_directory = ctx.work_directory; 

        ::ZeroMemory(&si, sizeof(si)); 
        si.cb = sizeof(si); 
        PROCESS_INFORMATION pi = detail::win32_start(entries[i].executable, entries[i].arguments, ctx.environment, sii, sio, sie, s); 

        if (!::CloseHandle(pi.hThread)) 
            boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch_pipeline: CloseHandle failed")); 

        cs.push_back(child(pi.dwProcessId, fhstdin, fhinvalid, fhinvalid, detail::file_handle(pi.hProcess))); 
    } 

    for (typename Entries::size_type i = 1; i < entries.size() - 1; ++i) 
    { 
        const typename Entries::value_type::context_type &ctx = entries[i].context; 

        BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); 
        detail::stream_info sii(close_stream(), false); 
        sii.type_ = detail::stream_info::use_handle; 
        sii.handle_ = pipes[i - 1].rend().release(); 

        detail::stream_info sio(close_stream(), true); 
        sio.type_ = detail::stream_info::use_handle; 
        sio.handle_ = pipes[i].wend().release(); 

        detail::stream_info sie(ctx.stderr_behavior, true); 

        s.work_directory = ctx.work_directory; 

        ::ZeroMemory(&si, sizeof(si)); 
        si.cb = sizeof(si); 
        PROCESS_INFORMATION pi = detail::win32_start(entries[i].executable, entries[i].arguments, ctx.environment, sii, sio, sie, s); 

        if (!::CloseHandle(pi.hThread)) 
            boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch_pipeline: CloseHandle failed")); 

        cs.push_back(child(pi.dwProcessId, fhinvalid, fhinvalid, fhinvalid, detail::file_handle(pi.hProcess))); 
    } 

    { 
        typename Entries::size_type i = entries.size() - 1; 
        const typename Entries::value_type::context_type &ctx = entries[i].context; 

        BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); 
        detail::stream_info sii(close_stream(), false); 
        sii.type_ = detail::stream_info::use_handle; 
        sii.handle_ = pipes[i - 1].rend().release(); 

        detail::file_handle fhstdout, fhstderr; 

        detail::stream_info sio(ctx.stdout_behavior, true); 
        if (sio.type_ == detail::stream_info::use_pipe) 
            fhstdout = sio.pipe_->rend(); 
        detail::stream_info sie(ctx.stderr_behavior, true); 
        if (sie.type_ == detail::stream_info::use_pipe) 
            fhstderr = sie.pipe_->rend(); 

        s.work_directory = ctx.work_directory; 

        ::ZeroMemory(&si, sizeof(si)); 
        si.cb = sizeof(si); 
        PROCESS_INFORMATION pi = detail::win32_start(entries[i].executable, entries[i].arguments, ctx.environment, sii, sio, sie, s); 

        if (!::CloseHandle(pi.hThread)) 
            boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch_pipeline: CloseHandle failed")); 

        cs.push_back(child(pi.dwProcessId, fhinvalid, fhstdout, fhstderr, detail::file_handle(pi.hProcess))); 
    } 
#endif 

    return cs; 
} 
int main()
{
    // integral
    same(false, false);
    diff(false, true);
    same('1', '1');
    diff('1', '2');
    same(static_cast<unsigned char>('1'), static_cast<unsigned char>('1'));
    diff(static_cast<unsigned char>('1'), static_cast<unsigned char>('2'));
    same(L'1', L'1');
    diff(L'1', L'2');
    same(u'1', u'1');
    diff(u'1', u'2');
    same(U'1', U'1');
    diff(U'1', U'2');
    same(static_cast<short>(1), static_cast<short>(1));
    diff(static_cast<short>(1), static_cast<short>(2));
    same(static_cast<unsigned short>(1), static_cast<unsigned short>(1));
    diff(static_cast<unsigned short>(1), static_cast<unsigned short>(2));
    same(1, 1);
    diff(1, 2);
    same(1u, 1u);
    diff(1u, 2u);
    same(1l, 1l);
    diff(1l, 2l);
    same(1ul, 1ul);
    diff(1ul, 2ul);
    same(1ll, 1ll);
    diff(1ll, 2ll);
    same(1ull, 1ull);
    diff(1ull, 2ull);

    // enum
    enum enums { enum1, enum2 };
    same(enum1, enum1);
    diff(enum1, enum2);

    // floating point
    checkFloatingPoint<float>();
    checkFloatingPoint<double>();
    checkFloatingPoint<long double>();

    // string
    same(std::string("hi"), std::string("hi"));
    diff(std::string("hi"), std::string("hj"));
    diff(std::string("hi"), std::string("hi2"));

    // bitset
    same(std::bitset<3>("101"), std::bitset<3>("101"));
    diff(std::bitset<3>("101"), std::bitset<3>("001"));
    diff(std::bitset<3>("101"), std::bitset<3>("111"));
    diff(std::bitset<3>("101"), std::bitset<3>("100"));

    // pair
    same(std::make_pair(1, '1'), std::make_pair(1, '1'));
    diff(std::make_pair(1, '1'), std::make_pair(2, '1'));
    diff(std::make_pair(1, '1'), std::make_pair(1, '2'));

    // tuple
    same(std::make_tuple(1, '1', 1.f), std::make_tuple(1, '1', 1.f));
    diff(std::make_tuple(1, '1', 1.f), std::make_tuple(2, '1', 1.f));
    diff(std::make_tuple(1, '1', 1.f), std::make_tuple(1, '2', 1.f));
    diff(std::make_tuple(1, '1', 1.f), std::make_tuple(1, '1', 2.f));

    // pointer
    int i1 = 1, i1b = 1, i2 = 2;
    int *pi1 = &i1, *pi1b = &i1b, * pi2 = &i2, * pin = nullptr;
    same(pi1, pi1);  // same addr
    same(pi1, pi1b); // diff addr, same value
    diff(pi1, pi2);  // diff addr, diff value
    same(pin, pin);  // nullptr, same
    diff(pin, pi1);  // nullptr, diff, avoid dereferenciation, first
    diff(pi1, pin);  // nullptr, diff, avoid dereferenciation, second

    std::unique_ptr<int> ui1(pi1), u2i1(pi1), ui1b(pi1b), ui2(pi2), uin(pin);
    same(ui1, ui1);
    same(ui1, u2i1); // diff object, same addr (even if it should not happen)
    same(ui1, ui1b);
    diff(ui1, ui2);
    same(uin, uin);
    diff(uin, ui1);
    diff(ui1, uin);
    ui1.release(); u2i1.release(); ui1b.release(); ui2.release(); uin.release();

    auto deleter = [](int *){};
    std::shared_ptr<int> si1(pi1, deleter), s2i1(pi1, deleter),
        si1b(pi1b, deleter), si2(pi2, deleter), sin(pin, deleter);
    same(si1, si1);
    same(si1, s2i1); // diff object, same addr (may happen since it is a shared_ptr)
    same(si1, si1b);
    diff(si1, si2);
    same(sin, sin);
    diff(sin, si1);
    diff(si1, sin);
    si1.reset(); s2i1.reset();
    si1b.reset(); si2.reset(); sin.reset();

    boost::shared_ptr<int> bsi1(pi1, deleter), bs2i1(pi1, deleter),
        bsi1b(pi1b, deleter), bsi2(pi2, deleter), bsin(pin, deleter);
    same(bsi1, bsi1);
    same(bsi1, bs2i1); // diff object, same addr (may happen since it is a shared_ptr)
    same(bsi1, bsi1b);
    diff(bsi1, bsi2);
    same(bsin, bsin);
    diff(bsin, bsi1);
    diff(bsi1, bsin);
    bsi1.reset(); bs2i1.reset();
    bsi1b.reset(); bsi2.reset(); bsin.reset();

    // C-style array
    int a123[] = {1, 2, 3}, a123b[] = {1, 2, 3}, a223[] = {2, 2, 3}, a133[] = {1, 3, 3}, a124[] = {1, 2, 4};
    same(a123, a123);
    same(a123, a123b);
    diff(a123, a223);
    diff(a123, a133);
    diff(a123, a124);
    same("hi", "hi");
    diff("hi", "hj");

    // array
    same(std::array<int, 3>{{1, 2, 3}}, std::array<int, 3>{{1, 2, 3}});
    diff(std::array<int, 3>{{1, 2, 3}}, std::array<int, 3>{{2, 2, 3}});
    diff(std::array<int, 3>{{1, 2, 3}}, std::array<int, 3>{{1, 3, 3}});
    diff(std::array<int, 3>{{1, 2, 3}}, std::array<int, 3>{{1, 2, 4}});

    // sequence
    checkSequence<std::vector<int>>();
    checkSequence<std::deque<int>>();
    checkSequence<std::forward_list<int>>();
    checkSequence<std::list<int>>();
    checkSequence<std::set<int>>();
    checkSequence<std::multiset<int>>();

    // mapping
    checkCommonMapping<std::map<int, int>>();

    // unordered mapping
    checkCommonMapping<std::unordered_map<int, int>>();

    return 0;
}
Beispiel #5
0
void TextLine::Test ()
{
  //
  // ctor
  //
  TextLine tl;
  assert (0 == tl._pStorage);
  assert (0 == tl._pData);
  assert (0 == tl._numAllocated);

  //
  // Init()
  //
  tl.Init ("howdy");
  assert (tl._pStorage);
  assert (tl._pData);
  assert (tl._pData >= tl._pStorage);
  assert (tl._numAllocated);
  assert (tl._numAllocated > strlen ("howdy"));
  assert (0 == strcmp (tl._pData, "howdy"));

  //
  // copy ctor
  //
  TextLine tl2 = tl;
  assert (tl2._pStorage);
  assert (tl2._pData);
  assert (tl2._pData >= tl._pStorage);
  assert (tl2._numAllocated);
  assert (tl2._numAllocated > strlen ("howdy"));
  assert (0 == strcmp (tl2._pData, "howdy"));

  //
  // op=
  //
  TextLine tl3;
  tl3 = tl;
  assert (tl3._pStorage);
  assert (tl3._pData);
  assert (tl3._pData >= tl._pStorage);
  assert (tl3._numAllocated);
  assert (tl3._numAllocated > strlen ("howdy"));
  assert (0 == strcmp (tl3._pData, "howdy"));

  //
  // GetLength()
  //
  assert (5 == tl.GetLength());

  //
  // Append()
  //
  bool stat;

  stat = tl.Append ('!');
  assert (stat);
  assert (0 == strcmp (tl._pData, "howdy!"));
  stat = tl.Append ('\\');
  assert (stat);
  assert (0 == strcmp (tl._pData, "howdy!\\"));
  stat = tl.Append ('\n');
  assert (stat);
  assert (0 == strcmp (tl._pData, "howdy!\\\n"));
  // we should be able to add chars after escaped newline
  stat = tl.Append (' ');
  assert (stat);
  assert (0 == strcmp (tl._pData, "howdy!\\\n "));
  stat = tl.Append ('\n');
  assert (stat);
  assert (0 == strcmp (tl._pData, "howdy!\\\n \n"));
  // we should not be able to add chars after non-escaped newline
  stat = tl.Append ('x');
  assert (! stat);
  assert (0 == strcmp (tl._pData, "howdy!\\\n \n"));
  stat = tl.Append ('y');
  assert (! stat);
  assert (0 == strcmp (tl._pData, "howdy!\\\n \n"));

  //
  // Consume()
  //
  char c;

  stat = tl2.Consume (c);
  assert (stat);
  assert ('h' == c);
  stat = tl2.Consume (c);
  assert (stat);
  assert ('o' == c);
  stat = tl2.Consume (c);
  assert (stat);
  assert ('w' == c);
  stat = tl2.Consume (c);
  assert (stat);
  assert ('d' == c);
  stat = tl2.Consume (c);
  assert (stat);
  assert ('y' == c);
  stat = tl2.Consume (c);
  assert (!stat);
  stat = tl2.Consume (c);
  assert (!stat);
  assert (! tl2.GetLength());

  //
  // Set/GetSourceInfo()
  //
  SourceInfo si1 ("this-file", 42);

  SourceInfo si2;
  si2 = tl.GetSourceInfo ();
  assert (0 == si2.GetLineNumber());
  assert (0 == si2.GetFileName());

  tl.SetSourceInfo (si1);
  si2 = tl.GetSourceInfo ();
  assert (42 == si2.GetLineNumber());
  assert (0 == strcmp ("this-file", si2.GetFileName()));
}
Beispiel #6
0
  void MeshFromSpline2D (SplineGeometry2d & geometry,
			 Mesh *& mesh, 
			 MeshingParameters & mp)
  {
    PrintMessage (1, "Generate Mesh from spline geometry");

    double h = mp.maxh;

    Box<2> bbox = geometry.GetBoundingBox ();

    if (bbox.Diam() < h) 
      {
	h = bbox.Diam();
	mp.maxh = h;
      }

    mesh = new Mesh;
    mesh->SetDimension (2);

    geometry.PartitionBoundary (h, *mesh);

    // marks mesh points for hp-refinement
    for (int i = 0; i < geometry.GetNP(); i++)
      if (geometry.GetPoint(i).hpref)
	{
	  double mindist = 1e99;
	  PointIndex mpi(0);
	  Point<2> gp = geometry.GetPoint(i);
	  Point<3> gp3(gp(0), gp(1), 0);
	  for (PointIndex pi = PointIndex::BASE; 
	       pi < mesh->GetNP()+PointIndex::BASE; pi++)
	    if (Dist2(gp3, (*mesh)[pi]) < mindist)
	      {
		mpi = pi;
		mindist = Dist2(gp3, (*mesh)[pi]);
	      }
	  (*mesh)[mpi].Singularity(1.);
	}


    int maxdomnr = 0;
    for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
      {
	if ( (*mesh)[si].domin > maxdomnr) maxdomnr = (*mesh)[si].domin;
	if ( (*mesh)[si].domout > maxdomnr) maxdomnr = (*mesh)[si].domout;
      }

    mesh->ClearFaceDescriptors();
    for (int i = 1; i <= maxdomnr; i++)
      mesh->AddFaceDescriptor (FaceDescriptor (i, 0, 0, i));

    // set Array<string*> bcnames... 
    // number of bcnames
    int maxsegmentindex = 0;
    for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
      {
	if ( (*mesh)[si].si > maxsegmentindex) maxsegmentindex = (*mesh)[si].si;
      }

    mesh->SetNBCNames(maxsegmentindex);

    for ( int sindex = 0; sindex < maxsegmentindex; sindex++ )
      mesh->SetBCName ( sindex, geometry.GetBCName( sindex+1 ) );

    for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
      (*mesh)[si].SetBCName ( (*mesh).GetBCNamePtr( (*mesh)[si].si-1 ) );

    Point3d pmin(bbox.PMin()(0), bbox.PMin()(1), -bbox.Diam());
    Point3d pmax(bbox.PMax()(0), bbox.PMax()(1), bbox.Diam());

    mesh->SetLocalH (pmin, pmax, mparam.grading);
    mesh->SetGlobalH (h);
  
    mesh->CalcLocalH();

    int bnp = mesh->GetNP(); // boundary points

    int hquad = mparam.quad;


    for (int domnr = 1; domnr <= maxdomnr; domnr++)
      if (geometry.GetDomainTensorMeshing (domnr))
        { // tensor product mesh
          
          Array<PointIndex, PointIndex::BASE> nextpi(bnp);
          Array<int, PointIndex::BASE> si1(bnp), si2(bnp);
          PointIndex firstpi;
          
          nextpi = -1;
          si1 = -1;
          si2 = -1;
          for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
            {
              int p1 = -1, p2 = -2;

              if ( (*mesh)[si].domin == domnr)
                { p1 = (*mesh)[si][0]; p2 = (*mesh)[si][1]; }
              if ( (*mesh)[si].domout == domnr)
                { p1 = (*mesh)[si][1]; p2 = (*mesh)[si][0]; }
              
              if (p1 == -1) continue;

              nextpi[p1] = p2;       // counter-clockwise
              
              int index = (*mesh)[si].si;
              if (si1[p1] != index && si2[p1] != index)
                { si2[p1] = si1[p1]; si1[p1] = index; }
              if (si1[p2] != index && si2[p2] != index)
                { si2[p2] = si1[p2]; si1[p2] = index; }
            }

          PointIndex c1(0), c2, c3, c4;  // 4 corner points
          int nex = 1, ney = 1;

          for (PointIndex pi = 1; pi <= si2.Size(); pi++)
            if (si2[pi] != -1)
              { c1 = pi; break; }      

          for (c2 = nextpi[c1]; si2[c2] == -1; c2 = nextpi[c2], nex++);
          for (c3 = nextpi[c2]; si2[c3] == -1; c3 = nextpi[c3], ney++);
          for (c4 = nextpi[c3]; si2[c4] == -1; c4 = nextpi[c4]);



          Array<PointIndex> pts ( (nex+1) * (ney+1) );   // x ... inner loop
          pts = -1;

          for (PointIndex pi = c1, i = 0; pi != c2; pi = nextpi[pi], i++)
            pts[i] = pi;
          for (PointIndex pi = c2, i = 0; pi != c3; pi = nextpi[pi], i++)
            pts[(nex+1)*i+nex] = pi;
          for (PointIndex pi = c3, i = 0; pi != c4; pi = nextpi[pi], i++)
            pts[(nex+1)*(ney+1)-i-1] = pi;
          for (PointIndex pi = c4, i = 0; pi != c1; pi = nextpi[pi], i++)
            pts[(nex+1)*(ney-i)] = pi;


          for (PointIndex pix = nextpi[c1], ix = 0; pix != c2; pix = nextpi[pix], ix++)
            for (PointIndex piy = nextpi[c2], iy = 0; piy != c3; piy = nextpi[piy], iy++)
              {
                Point<3> p = (*mesh)[pix] + ( (*mesh)[piy] - (*mesh)[c2] );
                pts[(nex+1)*(iy+1) + ix+1] = mesh -> AddPoint (p , 1, FIXEDPOINT);
              }

          for (int i = 0; i < ney; i++)
            for (int j = 0; j < nex; j++)
              {
                Element2d el(QUAD);
                el[0] = pts[i*(nex+1)+j];
                el[1] = pts[i*(nex+1)+j+1];
                el[2] = pts[(i+1)*(nex+1)+j+1];
                el[3] = pts[(i+1)*(nex+1)+j];
                el.SetIndex (domnr);

                mesh -> AddSurfaceElement (el);
              }
        }




    for (int domnr = 1; domnr <= maxdomnr; domnr++)
      {
        if (geometry.GetDomainTensorMeshing (domnr)) continue;

	if ( geometry.GetDomainMaxh ( domnr ) > 0 )
	  h = geometry.GetDomainMaxh(domnr);


	PrintMessage (3, "Meshing domain ", domnr, " / ", maxdomnr);

	int oldnf = mesh->GetNSE();

        mparam.quad = hquad || geometry.GetDomainQuadMeshing (domnr);

	Meshing2 meshing (Box<3> (pmin, pmax));

	for (PointIndex pi = PointIndex::BASE; pi < bnp+PointIndex::BASE; pi++)
	  meshing.AddPoint ( (*mesh)[pi], pi);
      

	PointGeomInfo gi;
	gi.trignum = 1;
	for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
	  {
	    if ( (*mesh)[si].domin == domnr)
	      meshing.AddBoundaryElement ( (*mesh)[si][0] + 1 - PointIndex::BASE, 
					   (*mesh)[si][1] + 1 - PointIndex::BASE, gi, gi);
	    if ( (*mesh)[si].domout == domnr)
	      meshing.AddBoundaryElement ( (*mesh)[si][1] + 1 - PointIndex::BASE, 
					   (*mesh)[si][0] + 1 - PointIndex::BASE, gi, gi);
	  }


	mparam.checkoverlap = 0;

	meshing.GenerateMesh (*mesh, h, domnr);

	for (SurfaceElementIndex sei = oldnf; sei < mesh->GetNSE(); sei++)
	  (*mesh)[sei].SetIndex (domnr);


	// astrid
	char * material;
	geometry.GetMaterial( domnr, material );
	if ( material )
	  {
	    (*mesh).SetMaterial ( domnr,  material );
	  }

      }

    mparam.quad = hquad;



    int hsteps = mp.optsteps2d;

    mp.optimize2d = "smcm"; 
    mp.optsteps2d = hsteps/2;
    Optimize2d (*mesh, mp);

    mp.optimize2d = "Smcm"; 
    mp.optsteps2d = (hsteps+1)/2;
    Optimize2d (*mesh, mp);

    mp.optsteps2d = hsteps;

    mesh->Compress();
    mesh -> SetNextMajorTimeStamp();


    extern void Render();
    Render();
  }