summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CGALCache.h5
-rw-r--r--src/CGALEvaluator.cc78
-rw-r--r--src/CGALEvaluator.h1
-rw-r--r--src/PolySetCache.h5
-rw-r--r--src/cache.h183
-rw-r--r--src/cgalutils.cc4
-rw-r--r--src/dxfdata.cc91
-rw-r--r--src/expr.cc5
-rw-r--r--src/handle_dep.cc12
-rw-r--r--src/myqhash.h16
-rw-r--r--src/openscad.cc1
-rw-r--r--src/qhash.cc19
12 files changed, 290 insertions, 130 deletions
diff --git a/src/CGALCache.h b/src/CGALCache.h
index 7d3a2d9..87e3343 100644
--- a/src/CGALCache.h
+++ b/src/CGALCache.h
@@ -1,8 +1,7 @@
#ifndef CGALCACHE_H_
#define CGALCACHE_H_
-#include "myqhash.h"
-#include <QCache>
+#include "cache.h"
/*!
*/
@@ -22,7 +21,7 @@ public:
private:
static CGALCache *inst;
- QCache<std::string, CGAL_Nef_polyhedron> cache;
+ Cache<std::string, CGAL_Nef_polyhedron> cache;
};
#endif
diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc
index 797434f..3646af2 100644
--- a/src/CGALEvaluator.cc
+++ b/src/CGALEvaluator.cc
@@ -28,6 +28,7 @@
#include <QRegExp>
#include <boost/foreach.hpp>
+#include <boost/unordered_map.hpp>
CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const AbstractNode &node)
{
@@ -392,9 +393,10 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
struct PolyReducer
{
Grid2d<int> grid;
- QHash< QPair<int,int>, QPair<int,int> > egde_to_poly;
- QHash< int, CGAL_Nef_polyhedron2::Point > points;
- QHash< int, QList<int> > polygons;
+ boost::unordered_map<std::pair<int,int>, std::pair<int,int> > edge_to_poly;
+ boost::unordered_map<int, CGAL_Nef_polyhedron2::Point> points;
+ typedef boost::unordered_map<int, std::vector<int> > PolygonMap;
+ PolygonMap polygons;
int poly_n;
void add_edges(int pn)
@@ -403,10 +405,10 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
int a = this->polygons[pn][j-1];
int b = this->polygons[pn][j % this->polygons[pn].size()];
if (a > b) { a = a^b; b = a^b; a = a^b; }
- if (this->egde_to_poly[QPair<int,int>(a, b)].first == 0)
- this->egde_to_poly[QPair<int,int>(a, b)].first = pn;
- else if (this->egde_to_poly[QPair<int,int>(a, b)].second == 0)
- this->egde_to_poly[QPair<int,int>(a, b)].second = pn;
+ if (this->edge_to_poly[std::pair<int,int>(a, b)].first == 0)
+ this->edge_to_poly[std::pair<int,int>(a, b)].first = pn;
+ else if (this->edge_to_poly[std::pair<int,int>(a, b)].second == 0)
+ this->edge_to_poly[std::pair<int,int>(a, b)].second = pn;
else
abort();
}
@@ -418,12 +420,12 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
int a = this->polygons[pn][j-1];
int b = this->polygons[pn][j % this->polygons[pn].size()];
if (a > b) { a = a^b; b = a^b; a = a^b; }
- if (this->egde_to_poly[QPair<int,int>(a, b)].first == pn)
- this->egde_to_poly[QPair<int,int>(a, b)].first = 0;
- if (this->egde_to_poly[QPair<int,int>(a, b)].second == pn)
- this->egde_to_poly[QPair<int,int>(a, b)].second = 0;
+ if (this->edge_to_poly[std::pair<int,int>(a, b)].first == pn)
+ this->edge_to_poly[std::pair<int,int>(a, b)].first = 0;
+ if (this->edge_to_poly[std::pair<int,int>(a, b)].second == pn)
+ this->edge_to_poly[std::pair<int,int>(a, b)].second = 0;
}
- this->polygons.remove(pn);
+ this->polygons.erase(pn);
}
PolyReducer(const PolySet &ps) : grid(GRID_COARSE), poly_n(1)
@@ -438,12 +440,13 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
// Filter away two vertices with the same index (due to grid)
// This could be done in a more general way, but we'd rather redo the entire
// grid concept instead.
- if (this->polygons[this->poly_n].indexOf(idx) == -1) {
- this->polygons[this->poly_n].append(this->grid.data(x, y));
+ std::vector<int> &poly = this->polygons[this->poly_n];
+ if (std::find(poly.begin(), poly.end(), idx) == poly.end()) {
+ poly.push_back(this->grid.data(x, y));
}
} else {
this->grid.align(x, y) = point_n;
- this->polygons[this->poly_n].append(point_n);
+ this->polygons[this->poly_n].push_back(point_n);
this->points[point_n] = CGAL_Nef_polyhedron2::Point(x, y);
point_n++;
}
@@ -453,7 +456,7 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
this->poly_n++;
}
else {
- this->polygons.remove(this->poly_n);
+ this->polygons.erase(this->poly_n);
}
}
}
@@ -462,11 +465,11 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
{
for (int i = 1; i < this->polygons[p1].size(); i++) {
int j = (p1e + i) % this->polygons[p1].size();
- this->polygons[this->poly_n].append(this->polygons[p1][j]);
+ this->polygons[this->poly_n].push_back(this->polygons[p1][j]);
}
for (int i = 1; i < this->polygons[p2].size(); i++) {
int j = (p2e + i) % this->polygons[p2].size();
- this->polygons[this->poly_n].append(this->polygons[p2][j]);
+ this->polygons[this->poly_n].push_back(this->polygons[p2][j]);
}
del_poly(p1);
del_poly(p2);
@@ -476,25 +479,22 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
void reduce()
{
- QList<int> work_queue;
- QHashIterator< int, QList<int> > it(polygons);
- while (it.hasNext()) {
- it.next();
- work_queue.append(it.key());
+ std::deque<int> work_queue;
+ BOOST_FOREACH(const PolygonMap::value_type &i, polygons) {
+ work_queue.push_back(i.first);
}
- while (!work_queue.isEmpty()) {
- int poly1_n = work_queue.first();
- work_queue.removeFirst();
- if (!this->polygons.contains(poly1_n))
- continue;
+ while (!work_queue.empty()) {
+ int poly1_n = work_queue.front();
+ work_queue.pop_front();
+ if (this->polygons.find(poly1_n) == this->polygons.end()) continue;
for (int j = 1; j <= this->polygons[poly1_n].size(); j++) {
int a = this->polygons[poly1_n][j-1];
int b = this->polygons[poly1_n][j % this->polygons[poly1_n].size()];
if (a > b) { a = a^b; b = a^b; a = a^b; }
- if (this->egde_to_poly[QPair<int,int>(a, b)].first != 0 &&
- this->egde_to_poly[QPair<int,int>(a, b)].second != 0) {
- int poly2_n = this->egde_to_poly[QPair<int,int>(a, b)].first +
- this->egde_to_poly[QPair<int,int>(a, b)].second - poly1_n;
+ if (this->edge_to_poly[std::pair<int,int>(a, b)].first != 0 &&
+ this->edge_to_poly[std::pair<int,int>(a, b)].second != 0) {
+ int poly2_n = this->edge_to_poly[std::pair<int,int>(a, b)].first +
+ this->edge_to_poly[std::pair<int,int>(a, b)].second - poly1_n;
int poly2_edge = -1;
for (int k = 1; k <= this->polygons[poly2_n].size(); k++) {
int c = this->polygons[poly2_n][k-1];
@@ -504,14 +504,14 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
poly2_edge = k-1;
continue;
}
- int poly3_n = this->egde_to_poly[QPair<int,int>(c, d)].first +
- this->egde_to_poly[QPair<int,int>(c, d)].second - poly2_n;
+ int poly3_n = this->edge_to_poly[std::pair<int,int>(c, d)].first +
+ this->edge_to_poly[std::pair<int,int>(c, d)].second - poly2_n;
if (poly3_n < 0)
continue;
if (poly3_n == poly1_n)
goto next_poly1_edge;
}
- work_queue.append(merge(poly1_n, j-1, poly2_n, poly2_edge));
+ work_queue.push_back(merge(poly1_n, j-1, poly2_n, poly2_edge));
goto next_poly1;
}
next_poly1_edge:;
@@ -524,12 +524,10 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
{
CGAL_Nef_polyhedron2 *N = new CGAL_Nef_polyhedron2;
- QHashIterator< int, QList<int> > it(polygons);
- while (it.hasNext()) {
- it.next();
+ BOOST_FOREACH(const PolygonMap::value_type &i, polygons) {
std::list<CGAL_Nef_polyhedron2::Point> plist;
- for (int j = 0; j < it.value().size(); j++) {
- int p = it.value()[j];
+ for (int j = 0; j < i.second.size(); j++) {
+ int p = i.second[j];
plist.push_back(points[p]);
}
*N += CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED);
diff --git a/src/CGALEvaluator.h b/src/CGALEvaluator.h
index 1dce4d9..7330796 100644
--- a/src/CGALEvaluator.h
+++ b/src/CGALEvaluator.h
@@ -1,7 +1,6 @@
#ifndef CGALEVALUATOR_H_
#define CGALEVALUATOR_H_
-#include "myqhash.h"
#include "visitor.h"
#include "CGAL_Nef_polyhedron.h"
#include "PolySetCGALEvaluator.h"
diff --git a/src/PolySetCache.h b/src/PolySetCache.h
index d1efeb7..d241fad 100644
--- a/src/PolySetCache.h
+++ b/src/PolySetCache.h
@@ -1,8 +1,7 @@
#ifndef POLYSETCACHE_H_
#define POLYSETCACHE_H_
-#include "myqhash.h"
-#include <QCache>
+#include "cache.h"
#include "memory.h"
class PolySetCache
@@ -28,7 +27,7 @@ private:
~cache_entry() { }
};
- QCache<std::string, cache_entry> cache;
+ Cache<std::string, cache_entry> cache;
};
#endif
diff --git a/src/cache.h b/src/cache.h
new file mode 100644
index 0000000..284c6da
--- /dev/null
+++ b/src/cache.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** OpenSCAD (www.openscad.org)
+** Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
+** Marius Kintel <marius@kintel.net>
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CACHE_H
+#define CACHE_H
+
+#include <boost/unordered_map.hpp>
+
+template <class Key, class T>
+class Cache
+{
+ struct Node {
+ inline Node() : keyPtr(0) {}
+ inline Node(T *data, int cost)
+ : keyPtr(0), t(data), c(cost), p(0), n(0) {}
+ const Key *keyPtr; T *t; int c; Node *p,*n;
+ };
+ typedef typename boost::unordered_map<Key, Node> map_type;
+ typedef typename map_type::iterator iterator_type;
+ typedef typename map_type::value_type value_type;
+
+ boost::unordered_map<Key, Node> hash;
+ Node *f, *l;
+ void *unused;
+ int mx, total;
+
+ inline void unlink(Node &n) {
+ if (n.p) n.p->n = n.n;
+ if (n.n) n.n->p = n.p;
+ if (l == &n) l = n.p;
+ if (f == &n) f = n.n;
+ total -= n.c;
+ T *obj = n.t;
+ hash.erase(*n.keyPtr);
+ delete obj;
+ }
+ inline T *relink(const Key &key) {
+ iterator_type i = hash.find(key);
+ if (i == hash.end()) return 0;
+
+ Node &n = i->second;
+ if (f != &n) {
+ if (n.p) n.p->n = n.n;
+ if (n.n) n.n->p = n.p;
+ if (l == &n) l = n.p;
+ n.p = 0;
+ n.n = f;
+ f->p = &n;
+ f = &n;
+ }
+ return n.t;
+ }
+
+public:
+ inline explicit Cache(int maxCost = 100)
+ : f(0), l(0), unused(0), mx(maxCost), total(0) { }
+ inline ~Cache() { clear(); }
+
+ inline int maxCost() const { return mx; }
+ void setMaxCost(int m) { mx = m; trim(mx); }
+ inline int totalCost() const { return total; }
+
+ inline int size() const { return hash.size(); }
+ inline bool empty() const { return hash.empty(); }
+
+ void clear() {
+ while (f) { delete f->t; f = f->n; }
+ hash.clear(); l = 0; total = 0;
+ }
+
+ bool insert(const Key &key, T *object, int cost = 1);
+ T *object(const Key &key) const { return const_cast<Cache<Key,T>*>(this)->relink(key); }
+ inline bool contains(const Key &key) const { return hash.find(key) != hash.end(); }
+ T *operator[](const Key &key) const { return object(key); }
+
+ bool remove(const Key &key);
+ T *take(const Key &key);
+
+private:
+ void trim(int m);
+};
+
+template <class Key, class T>
+inline bool Cache<Key,T>::remove(const Key &key)
+{
+ iterator_type i = hash.find(key);
+ if (i == hash.end()) {
+ return false;
+ } else {
+ unlink(i->second);
+ return true;
+ }
+}
+
+template <class Key, class T>
+inline T *Cache<Key,T>::take(const Key &key)
+{
+ iterator_type i = hash.find(key);
+ if (i == hash.end()) return 0;
+
+ Node &n = *i;
+ T *t = n.t;
+ n.t = 0;
+ unlink(n);
+ return t;
+}
+
+template <class Key, class T>
+bool Cache<Key,T>::insert(const Key &akey, T *aobject, int acost)
+{
+ remove(akey);
+ if (acost > mx) {
+ delete aobject;
+ return false;
+ }
+ trim(mx - acost);
+ Node node(aobject, acost);
+ hash[akey] = node;
+ iterator_type i = hash.find(akey);
+ total += acost;
+ Node *n = &i->second;
+ n->keyPtr = &i->first;
+ if (f) f->p = n;
+ n->n = f;
+ f = n;
+ if (!l) l = f;
+ return true;
+}
+
+template <class Key, class T>
+void Cache<Key,T>::trim(int m)
+{
+ Node *n = l;
+ while (n && total > m) {
+ Node *u = n;
+ n = n->p;
+ unlink(*u);
+ }
+}
+
+#endif
+
diff --git a/src/cgalutils.cc b/src/cgalutils.cc
index bef873c..e77f5dd 100644
--- a/src/cgalutils.cc
+++ b/src/cgalutils.cc
@@ -8,6 +8,8 @@
#include <CGAL/assertions_behaviour.h>
#include <CGAL/exceptions.h>
+#include <map>
+
PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p)
{
PolySet *ps = new PolySet();
@@ -87,7 +89,7 @@ public:
for (size_t i = 0; i < ps.polygons.size(); i++) {
const PolySet::Polygon *poly = &ps.polygons[i];
- QHash<int,int> fc;
+ std::map<int,int> fc;
bool facet_is_degenerated = false;
for (size_t j = 0; j < poly->size(); j++) {
const Vector3d &p = poly->at(j);
diff --git a/src/dxfdata.cc b/src/dxfdata.cc
index 10f3b0c..bf689f7 100644
--- a/src/dxfdata.cc
+++ b/src/dxfdata.cc
@@ -24,19 +24,19 @@
*
*/
-#include "myqhash.h"
#include "dxfdata.h"
#include "grid.h"
#include "printutils.h"
#include "handle_dep.h"
#include "openscad.h" // get_fragments_from_r()
-#include <QFile>
-#include <QTextStream>
+#include <fstream>
#include "mathc99.h"
#include <assert.h>
#include <boost/unordered_map.hpp>
#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
#include <algorithm>
struct Line {
@@ -58,12 +58,11 @@ DxfData::DxfData(double fn, double fs, double fa,
{
handle_dep(filename); // Register ourselves as a dependency
- QFile f(QString::fromStdString(filename));
- if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ std::ifstream stream(filename.c_str());
+ if (!stream.good()) {
PRINTF("WARNING: Can't open DXF file `%s'.", filename.c_str());
return;
}
- QTextStream stream(&f);
Grid2d< std::vector<int> > grid(GRID_COARSE);
std::vector<Line> lines; // Global lines
@@ -111,35 +110,41 @@ DxfData::DxfData(double fn, double fs, double fa,
//
// Parse DXF file. Will populate this->points, this->dims, lines and blockdata
//
- while (!stream.atEnd())
+ while (!stream.eof())
{
- QString id_str = stream.readLine();
- QString data = stream.readLine();
-
- bool status;
- int id = id_str.toInt(&status);
-
- if (!status) {
- PRINTF("WARNING: Illegal ID `%s' in `%s'.", id_str.toUtf8().data(), filename.c_str());
+ std::string id_str, data;
+ std::getline(stream, id_str);
+ boost::trim(id_str);
+ std::getline(stream, data);
+ boost::trim(data);
+
+ int id;
+ try {
+ id = boost::lexical_cast<int>(id_str);
+ }
+ catch (boost::bad_lexical_cast &blc) {
+ if (!stream.eof()) {
+ PRINTF("WARNING: Illegal ID '%s' in `%s'", id_str.c_str(), filename.c_str());
+ }
break;
- }
-
+ }
+ try {
if (id >= 10 && id <= 16) {
if (in_blocks_section)
- coords[id-10][0] = data.toDouble();
+ coords[id-10][0] = boost::lexical_cast<double>(data);
else if (id == 11 || id == 12 || id == 16)
- coords[id-10][0] = data.toDouble() * scale;
+ coords[id-10][0] = boost::lexical_cast<double>(data) * scale;
else
- coords[id-10][0] = (data.toDouble() - xorigin) * scale;
+ coords[id-10][0] = (boost::lexical_cast<double>(data) - xorigin) * scale;
}
if (id >= 20 && id <= 26) {
if (in_blocks_section)
- coords[id-20][1] = data.toDouble();
+ coords[id-20][1] = boost::lexical_cast<double>(data);
else if (id == 21 || id == 22 || id == 26)
- coords[id-20][1] = data.toDouble() * scale;
+ coords[id-20][1] = boost::lexical_cast<double>(data) * scale;
else
- coords[id-20][1] = (data.toDouble() - yorigin) * scale;
+ coords[id-20][1] = (boost::lexical_cast<double>(data) - yorigin) * scale;
}
switch (id)
@@ -275,7 +280,7 @@ DxfData::DxfData(double fn, double fs, double fa,
(layername.empty() || layername == layer))) {
unsupported_entities_list[mode]++;
}
- mode = data.toStdString();
+ mode = data;
layer.erase();
name.erase();
iddata.erase();
@@ -292,70 +297,74 @@ DxfData::DxfData(double fn, double fs, double fa,
}
break;
case 1:
- name = data.toStdString();
+ name = data;
break;
case 2:
- iddata = data.toStdString();
+ iddata = data;
break;
case 8:
- layer = data.toStdString();
+ layer = data;
break;
case 10:
if (in_blocks_section)
- xverts.push_back((data.toDouble()));
+ xverts.push_back((boost::lexical_cast<double>(data)));
else
- xverts.push_back((data.toDouble() - xorigin) * scale);
+ xverts.push_back((boost::lexical_cast<double>(data) - xorigin) * scale);
break;
case 11:
if (in_blocks_section)
- xverts.push_back((data.toDouble()));
+ xverts.push_back((boost::lexical_cast<double>(data)));
else
- xverts.push_back((data.toDouble() - xorigin) * scale);
+ xverts.push_back((boost::lexical_cast<double>(data) - xorigin) * scale);
break;
case 20:
if (in_blocks_section)
- yverts.push_back((data.toDouble()));
+ yverts.push_back((boost::lexical_cast<double>(data)));
else
- yverts.push_back((data.toDouble() - yorigin) * scale);
+ yverts.push_back((boost::lexical_cast<double>(data) - yorigin) * scale);
break;
case 21:
if (in_blocks_section)
- yverts.push_back((data.toDouble()));
+ yverts.push_back((boost::lexical_cast<double>(data)));
else
- yverts.push_back((data.toDouble() - yorigin) * scale);
+ yverts.push_back((boost::lexical_cast<double>(data) - yorigin) * scale);
break;
case 40:
// CIRCLE, ARC: radius
// ELLIPSE: minor to major ratio
// DIMENSION (radial, diameter): Leader length
- radius = data.toDouble();
+ radius = boost::lexical_cast<double>(data);
if (!in_blocks_section) radius *= scale;
break;
case 41:
// ELLIPSE: start_angle
// INSERT: X scale
- ellipse_start_angle = data.toDouble();
+ ellipse_start_angle = boost::lexical_cast<double>(data);
break;
case 50:
// ARC: start_angle
// INSERT: rot angle
// DIMENSION: linear and rotated: angle
- arc_start_angle = data.toDouble();
+ arc_start_angle = boost::lexical_cast<double>(data);
break;
case 42:
// ELLIPSE: stop_angle
// INSERT: Y scale
- ellipse_stop_angle = data.toDouble();
+ ellipse_stop_angle = boost::lexical_cast<double>(data);
break;
case 51: // ARC
- arc_stop_angle = data.toDouble();
+ arc_stop_angle = boost::lexical_cast<double>(data);
break;
case 70:
// LWPOLYLINE: polyline flag
// DIMENSION: dimension type
- dimtype = data.toInt();
+ dimtype = boost::lexical_cast<int>(data);
break;
}
+ }
+ catch (boost::bad_lexical_cast &blc) {
+ PRINTF("WARNING: Illegal value %s in `%s'", data.c_str(), filename.c_str());
+ }
}
BOOST_FOREACH(const EntityList::value_type &i, unsupported_entities_list) {
diff --git a/src/expr.cc b/src/expr.cc
index fc1fbf0..7e1a25b 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -85,6 +85,11 @@ Value Expression::evaluate(const Context *context) const
if (i >= 0 && i < int(v1.vec.size()))
return *v1.vec[i];
}
+ if (v1.type == Value::STRING && v2.type == Value::NUMBER) {
+ int i = (int)(v2.num);
+ if (i >= 0 && i < v1.text.size())
+ return Value(v1.text.substr(i, 1));
+ }
return Value();
}
if (this->type == "I")
diff --git a/src/handle_dep.cc b/src/handle_dep.cc
index 2a05b4a..d4380f5 100644
--- a/src/handle_dep.cc
+++ b/src/handle_dep.cc
@@ -1,13 +1,14 @@
#include "handle_dep.h"
-#include "myqhash.h"
#include <string>
#include <sstream>
#include <QString>
#include <QDir>
#include <QSet>
#include <stdlib.h> // for system()
+#include <boost/unordered_set.hpp>
+#include <boost/foreach.hpp>
-QSet<std::string> dependencies;
+boost::unordered_set<std::string> dependencies;
const char *make_command = NULL;
void handle_dep(const std::string &filename)
@@ -33,9 +34,10 @@ bool write_deps(const std::string &filename, const std::string &output_file)
return false;
}
fprintf(fp, "%s:", output_file.c_str());
- QSetIterator<std::string> i(dependencies);
- while (i.hasNext())
- fprintf(fp, " \\\n\t%s", i.next().c_str());
+
+ BOOST_FOREACH(const std::string &str, dependencies) {
+ fprintf(fp, " \\\n\t%s", str.c_str());
+ }
fprintf(fp, "\n");
fclose(fp);
return true;
diff --git a/src/myqhash.h b/src/myqhash.h
deleted file mode 100644
index 9156ec2..0000000
--- a/src/myqhash.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef OPENSCAD_QHASH_H_
-#define OPENSCAD_QHASH_H_
-
-/*!
- Defines a qHash for std::string.
-
- Note that this header must be included before Qt headers (at least
- before qhash.h) to take effect.
- */
-
-#include <qglobal.h>
-#include <string>
-extern uint qHash(const std::string &);
-#include <QHash>
-
-#endif
diff --git a/src/openscad.cc b/src/openscad.cc
index d708a8e..67112d8 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -24,7 +24,6 @@
*
*/
-#include "myqhash.h"
#include "openscad.h"
#include "MainWindow.h"
#include "node.h"
diff --git a/src/qhash.cc b/src/qhash.cc
deleted file mode 100644
index cec9adf..0000000
--- a/src/qhash.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "myqhash.h"
-
-static uint hash(const uchar *p, int n)
-{
- uint h = 0;
- uint g;
-
- while (n--) {
- h = (h << 4) + *p++;
- if ((g = (h & 0xf0000000)) != 0)
- h ^= g >> 23;
- h &= ~g;
- }
- return h;
-}
-
-uint qHash(const std::string &str) {
- return hash(reinterpret_cast<const uchar *>(str.c_str()), str.length());
-}
contact: Jan Huwald // Impressum