Commit bf44e21ad6728c825ed4e28fceba190a68435ab0

Authored by Charles Otto
1 parent 94463713

Update several c-api functions to take string buffers as input

Instead of returning references to static memory (which are invalidated by
subsequent or concurrent calls to the function), require users to input string
buffers to functions that return strings.

Affected functions:
br_get_filename
br_get_metadata_string
br_scratch_path
br_objects
br_most_recent_message

In some GUI functions, use C++ functions instead of going through the c api
add a c++ method correspondign to br_objects (which returns a stringlist
instead of merging the lines)

br_read_pipe and br_get_header also use static memory in a similar way, but
are not addressed in this commit.
app/br/br.cpp
@@ -171,7 +171,11 @@ public: @@ -171,7 +171,11 @@ public:
171 // Do nothing because we checked for this flag prior to initialization 171 // Do nothing because we checked for this flag prior to initialization
172 } else if (!strcmp(fun, "objects")) { 172 } else if (!strcmp(fun, "objects")) {
173 check(parc <= 2, "Incorrect parameter count for 'objects'."); 173 check(parc <= 2, "Incorrect parameter count for 'objects'.");
174 - printf("%s\n", br_objects(parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*")); 174 + int size = br_objects(NULL, 0, parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*");
  175 + char * temp = new char[size];
  176 + br_objects(temp, size, parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*");
  177 + printf("%s\n", temp);
  178 + delete [] temp;
175 } else if (!strcmp(fun, "about")) { 179 } else if (!strcmp(fun, "about")) {
176 check(parc == 0, "No parameters expected for 'about'."); 180 check(parc == 0, "No parameters expected for 'about'.");
177 printf("%s\n", br_about()); 181 printf("%s\n", br_about());
openbr/gui/algorithm.cpp
1 #include <QStringList> 1 #include <QStringList>
2 #include <openbr/openbr.h> 2 #include <openbr/openbr.h>
  3 +#include <openbr/openbr_plugin.h>
3 4
4 #include "algorithm.h" 5 #include "algorithm.h"
5 6
@@ -18,7 +19,7 @@ bool br::Algorithm::addAlgorithm(const QString &amp;algorithm, const QString &amp;displa @@ -18,7 +19,7 @@ bool br::Algorithm::addAlgorithm(const QString &amp;algorithm, const QString &amp;displa
18 { 19 {
19 static QStringList availableAlgorithms; 20 static QStringList availableAlgorithms;
20 if (availableAlgorithms.isEmpty()) 21 if (availableAlgorithms.isEmpty())
21 - availableAlgorithms = QString(br_objects("Abbreviation", ".*", false)).split("\n"); 22 + availableAlgorithms = br::Context::objects("Abbreviation", ".*", false);
22 23
23 if (!availableAlgorithms.contains(algorithm)) 24 if (!availableAlgorithms.contains(algorithm))
24 return false; 25 return false;
openbr/gui/gallerytoolbar.cpp
@@ -84,7 +84,7 @@ void br::GalleryToolBar::_enroll(const br::File &amp;input) @@ -84,7 +84,7 @@ void br::GalleryToolBar::_enroll(const br::File &amp;input)
84 galleryLock.lock(); 84 galleryLock.lock();
85 this->input = input; 85 this->input = input;
86 if (input.suffix() == "gal") gallery = input.name + ".mem"; 86 if (input.suffix() == "gal") gallery = input.name + ".mem";
87 - else gallery = QString("%1/galleries/%2.gal[cache]").arg(br_scratch_path(), qPrintable(input.baseName()+input.hash())); 87 + else gallery = QString("%1/galleries/%2.gal[cache]").arg(br::Globals->scratchPath(), qPrintable(input.baseName()+input.hash()));
88 files = br::Enroll(input.flat(), gallery.flat()); 88 files = br::Enroll(input.flat(), gallery.flat());
89 galleryLock.unlock(); 89 galleryLock.unlock();
90 } 90 }
@@ -148,7 +148,7 @@ void br::GalleryToolBar::home() @@ -148,7 +148,7 @@ void br::GalleryToolBar::home()
148 148
149 void br::GalleryToolBar::mean() 149 void br::GalleryToolBar::mean()
150 { 150 {
151 - const QString file = QString("%1/mean/%2.png").arg(br_scratch_path(), input.baseName()+input.hash()); 151 + const QString file = QString("%1/mean/%2.png").arg(br::Globals->scratchPath(), input.baseName()+input.hash());
152 br_set_property("CENTER_TRAIN_B", qPrintable(file)); 152 br_set_property("CENTER_TRAIN_B", qPrintable(file));
153 br::File trainingFile = input; 153 br::File trainingFile = input;
154 br_train(qPrintable(trainingFile.flat()), "[algorithm=MedianFace]"); 154 br_train(qPrintable(trainingFile.flat()), "[algorithm=MedianFace]");
openbr/gui/progress.cpp
1 #include <openbr/openbr.h> 1 #include <openbr/openbr.h>
  2 +#include <openbr/openbr_plugin.h>
2 3
3 #include "progress.h" 4 #include "progress.h"
4 5
@@ -29,7 +30,7 @@ void br::Progress::checkProgress() @@ -29,7 +30,7 @@ void br::Progress::checkProgress()
29 const bool visible = progress >= 0 && progress < 100; 30 const bool visible = progress >= 0 && progress < 100;
30 31
31 if (visible) { 32 if (visible) {
32 - showMessage(br_most_recent_message()); 33 + showMessage(Globals->mostRecentMessage);
33 pbProgress.setValue(progress); 34 pbProgress.setValue(progress);
34 if (progress > 100) pbProgress.setMaximum(0); 35 if (progress > 100) pbProgress.setMaximum(0);
35 else pbProgress.setMaximum(100); 36 else pbProgress.setMaximum(100);
openbr/gui/templateviewer.cpp
@@ -72,7 +72,7 @@ void TemplateViewer::refreshImage() @@ -72,7 +72,7 @@ void TemplateViewer::refreshImage()
72 if (file.isNull() || (format == "Photo")) { 72 if (file.isNull() || (format == "Photo")) {
73 setImage(file, true); 73 setImage(file, true);
74 } else { 74 } else {
75 - const QString path = QString(br_scratch_path()) + "/thumbnails"; 75 + const QString path = QString(br::Globals->scratchPath()) + "/thumbnails";
76 const QString hash = file.hash()+format; 76 const QString hash = file.hash()+format;
77 const QString processedFile = path+"/"+file.baseName()+hash+".png"; 77 const QString processedFile = path+"/"+file.baseName()+hash+".png";
78 if (!QFileInfo(processedFile).exists()) { 78 if (!QFileInfo(processedFile).exists()) {
openbr/gui/transformeditor.cpp
@@ -24,7 +24,7 @@ using namespace br; @@ -24,7 +24,7 @@ using namespace br;
24 br::TransformEditor::TransformEditor(Transform *transform, QWidget *parent) 24 br::TransformEditor::TransformEditor(Transform *transform, QWidget *parent)
25 : QWidget(parent) 25 : QWidget(parent)
26 { 26 {
27 - name.addItems(QString(br_objects("Transform", ".*", false)).split('\n')); 27 + name.addItems(br::Context::objects("Transform", ".*", false));
28 layout.addWidget(&name); 28 layout.addWidget(&name);
29 setLayout(&layout); 29 setLayout(&layout);
30 30
openbr/openbr.cpp
@@ -28,6 +28,21 @@ @@ -28,6 +28,21 @@
28 28
29 using namespace br; 29 using namespace br;
30 30
  31 +static int partialCopy(const QString & string, char * buffer, int buffer_length)
  32 +{
  33 +
  34 + QByteArray byteArray = string.toLocal8Bit();
  35 +
  36 + int copyLength = std::min(buffer_length-1, byteArray.size());
  37 + if (copyLength < 0)
  38 + return byteArray.size() + 1;
  39 +
  40 + memcpy(buffer, byteArray.data(), copyLength);
  41 + buffer[copyLength] = '\0';
  42 +
  43 + return byteArray.size() + 1;
  44 +}
  45 +
31 const char *br_about() 46 const char *br_about()
32 { 47 {
33 static QMutex aboutLock; 48 static QMutex aboutLock;
@@ -153,53 +168,14 @@ void br_make_pairwise_mask(const char *target_input, const char *query_input, co @@ -153,53 +168,14 @@ void br_make_pairwise_mask(const char *target_input, const char *query_input, co
153 BEE::makePairwiseMask(target_input, query_input, mask); 168 BEE::makePairwiseMask(target_input, query_input, mask);
154 } 169 }
155 170
156 -const char *br_most_recent_message() 171 +int br_most_recent_message(char * buffer, int buffer_length)
157 { 172 {
158 - static QByteArray byteArray;  
159 - byteArray = Globals->mostRecentMessage.toLocal8Bit();  
160 - return byteArray.data(); 173 + return partialCopy(Globals->mostRecentMessage, buffer, buffer_length);
161 } 174 }
162 175
163 -const char *br_objects(const char *abstractions, const char *implementations, bool parameters) 176 +int br_objects(char * buffer, int buffer_length, const char *abstractions, const char *implementations, bool parameters)
164 { 177 {
165 - static QByteArray objects;  
166 -  
167 - QStringList objectList;  
168 - QRegExp abstractionsRegExp(abstractions);  
169 - QRegExp implementationsRegExp(implementations);  
170 -  
171 - if (abstractionsRegExp.exactMatch("Abbreviation"))  
172 - foreach (const QString &name, Globals->abbreviations.keys())  
173 - if (implementationsRegExp.exactMatch(name))  
174 - objectList.append(name + (parameters ? "\t" + Globals->abbreviations[name] : ""));  
175 -  
176 - if (abstractionsRegExp.exactMatch("Distance"))  
177 - foreach (const QString &name, Factory<Distance>::names())  
178 - if (implementationsRegExp.exactMatch(name))  
179 - objectList.append(name + (parameters ? "\t" + Factory<Distance>::parameters(name) : ""));  
180 -  
181 - if (abstractionsRegExp.exactMatch("Format"))  
182 - foreach (const QString &name, Factory<Format>::names())  
183 - if (implementationsRegExp.exactMatch(name))  
184 - objectList.append(name + (parameters ? "\t" + Factory<Format>::parameters(name) : ""));  
185 -  
186 - if (abstractionsRegExp.exactMatch("Initializer"))  
187 - foreach (const QString &name, Factory<Initializer>::names())  
188 - if (implementationsRegExp.exactMatch(name))  
189 - objectList.append(name + (parameters ? "\t" + Factory<Initializer>::parameters(name) : ""));  
190 -  
191 - if (abstractionsRegExp.exactMatch("Output"))  
192 - foreach (const QString &name, Factory<Output>::names())  
193 - if (implementationsRegExp.exactMatch(name))  
194 - objectList.append(name + (parameters ? "\t" + Factory<Output>::parameters(name) : ""));  
195 -  
196 - if (abstractionsRegExp.exactMatch("Transform"))  
197 - foreach (const QString &name, Factory<Transform>::names())  
198 - if (implementationsRegExp.exactMatch(name))  
199 - objectList.append(name + (parameters ? "\t" + Factory<Transform>::parameters(name) : ""));  
200 -  
201 - objects = objectList.join("\n").toLocal8Bit();  
202 - return objects.data(); 178 + return partialCopy(br::Context::objects(abstractions, implementations, parameters).join('\n'), buffer, buffer_length);
203 } 179 }
204 180
205 bool br_plot(int num_files, const char *files[], const char *destination, bool show) 181 bool br_plot(int num_files, const char *files[], const char *destination, bool show)
@@ -254,11 +230,9 @@ void br_read_pipe(const char *pipe, int *argc, char ***argv) @@ -254,11 +230,9 @@ void br_read_pipe(const char *pipe, int *argc, char ***argv)
254 *argv = rawCharArrayList.data(); 230 *argv = rawCharArrayList.data();
255 } 231 }
256 232
257 -const char *br_scratch_path() 233 +int br_scratch_path(char * buffer, int buffer_length)
258 { 234 {
259 - static QByteArray byteArray;  
260 - byteArray = Context::scratchPath().toLocal8Bit();  
261 - return byteArray.data(); 235 + return partialCopy(Context::scratchPath(), buffer, buffer_length);
262 } 236 }
263 237
264 const char *br_sdk_path() 238 const char *br_sdk_path()
@@ -387,11 +361,9 @@ bool br_img_is_empty(br_template tmpl) @@ -387,11 +361,9 @@ bool br_img_is_empty(br_template tmpl)
387 return t->m().empty(); 361 return t->m().empty();
388 } 362 }
389 363
390 -const char* br_get_filename(br_template tmpl) 364 +int br_get_filename(br_template tmpl, char * buffer, int buffer_length)
391 { 365 {
392 - static QByteArray buffer;  
393 - buffer = reinterpret_cast<Template*>(tmpl)->file.name.toLocal8Bit();  
394 - return buffer.data(); 366 + return partialCopy(reinterpret_cast<Template*>(tmpl)->file.name, buffer, buffer_length);
395 } 367 }
396 368
397 void br_set_filename(br_template tmpl, const char *filename) 369 void br_set_filename(br_template tmpl, const char *filename)
@@ -400,15 +372,11 @@ void br_set_filename(br_template tmpl, const char *filename) @@ -400,15 +372,11 @@ void br_set_filename(br_template tmpl, const char *filename)
400 t->file.name = filename; 372 t->file.name = filename;
401 } 373 }
402 374
403 -const char* br_get_metadata_string(br_template tmpl, const char *key) 375 +int br_get_metadata_string(br_template tmpl, const char *key, char * buffer, int buffer_length)
404 { 376 {
405 Template *t = reinterpret_cast<Template*>(tmpl); 377 Template *t = reinterpret_cast<Template*>(tmpl);
406 - // need an object outside of this scope  
407 - // so the char pointer is valid  
408 - static QByteArray result;  
409 QVariant qvar = t->file.value(key); 378 QVariant qvar = t->file.value(key);
410 - result = QtUtils::toString(qvar).toUtf8();  
411 - return result.data(); 379 + return partialCopy(QtUtils::toString(qvar), buffer, buffer_length);
412 } 380 }
413 381
414 br_template_list br_enroll_template(br_template tmpl) 382 br_template_list br_enroll_template(br_template tmpl)
openbr/openbr.h
@@ -41,6 +41,10 @@ extern &quot;C&quot; { @@ -41,6 +41,10 @@ extern &quot;C&quot; {
41 * \section managed_return_value Managed Return Value 41 * \section managed_return_value Managed Return Value
42 * Memory for <tt>const char*</tt> return values is managed internally and guaranteed until the next call to the function. 42 * Memory for <tt>const char*</tt> return values is managed internally and guaranteed until the next call to the function.
43 * 43 *
  44 + * \section input_string_buffer Input String Buffer
  45 + * Users should input a char * buffer and the size of that buffer. String data will be copied into the buffer, if the buffer is too
  46 + * small, only part of the string will be copied. Returns the buffer size required to contain the complete string.
  47 + *
44 * \section examples Examples 48 * \section examples Examples
45 * - \ref c_face_recognition_evaluation 49 * - \ref c_face_recognition_evaluation
46 * 50 *
@@ -255,10 +259,10 @@ BR_EXPORT void br_make_pairwise_mask(const char *target_input, const char *query @@ -255,10 +259,10 @@ BR_EXPORT void br_make_pairwise_mask(const char *target_input, const char *query
255 259
256 /*! 260 /*!
257 * \brief Returns the most recent line sent to stderr. 261 * \brief Returns the most recent line sent to stderr.
258 - * \note \ref managed_return_value 262 + * \note \ref input_string_buffer
259 * \see br_progress br_time_remaining 263 * \see br_progress br_time_remaining
260 */ 264 */
261 -BR_EXPORT const char *br_most_recent_message(); 265 +BR_EXPORT int br_most_recent_message(char * buffer, int buffer_length);
262 266
263 /*! 267 /*!
264 * \brief Returns names and parameters for the requested objects. 268 * \brief Returns names and parameters for the requested objects.
@@ -267,10 +271,10 @@ BR_EXPORT const char *br_most_recent_message(); @@ -267,10 +271,10 @@ BR_EXPORT const char *br_most_recent_message();
267 * \param abstractions Regular expression of the abstractions to search. 271 * \param abstractions Regular expression of the abstractions to search.
268 * \param implementations Regular expression of the implementations to search. 272 * \param implementations Regular expression of the implementations to search.
269 * \param parameters Include parameters after object name. 273 * \param parameters Include parameters after object name.
270 - * \note \ref managed_return_value 274 + * \note \ref input_string_buffer
271 * \note This function uses Qt's <a href="http://doc.qt.digia.com/stable/qregexp.html">QRegExp</a> syntax. 275 * \note This function uses Qt's <a href="http://doc.qt.digia.com/stable/qregexp.html">QRegExp</a> syntax.
272 */ 276 */
273 -BR_EXPORT const char *br_objects(const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true); 277 +BR_EXPORT int br_objects(char * buffer, int buffer_length, const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true);
274 278
275 /*! 279 /*!
276 * \brief Renders recognition performance figures for a set of <tt>.csv</tt> files created by \ref br_eval. 280 * \brief Renders recognition performance figures for a set of <tt>.csv</tt> files created by \ref br_eval.
@@ -375,9 +379,11 @@ BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv); @@ -375,9 +379,11 @@ BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv);
375 379
376 /*! 380 /*!
377 * \brief Wraps br::Context::scratchPath() 381 * \brief Wraps br::Context::scratchPath()
  382 + * \note \ref input_string_buffer
378 * \see br_version 383 * \see br_version
379 */ 384 */
380 -BR_EXPORT const char *br_scratch_path(); 385 +BR_EXPORT int br_scratch_path(char * buffer, int buffer_length);
  386 +
381 387
382 /*! 388 /*!
383 * \brief Returns the full path to the root of the SDK. 389 * \brief Returns the full path to the root of the SDK.
@@ -433,7 +439,6 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode @@ -433,7 +439,6 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode
433 439
434 /*! 440 /*!
435 * \brief Wraps br::Context::version() 441 * \brief Wraps br::Context::version()
436 - * \note \ref managed_return_value  
437 * \see br_about br_scratch_path 442 * \see br_about br_scratch_path
438 */ 443 */
439 BR_EXPORT const char *br_version(); 444 BR_EXPORT const char *br_version();
@@ -505,16 +510,18 @@ BR_EXPORT int br_img_channels(br_template tmpl); @@ -505,16 +510,18 @@ BR_EXPORT int br_img_channels(br_template tmpl);
505 BR_EXPORT bool br_img_is_empty(br_template tmpl); 510 BR_EXPORT bool br_img_is_empty(br_template tmpl);
506 /*! 511 /*!
507 * \brief Get the filename for a br::Template 512 * \brief Get the filename for a br::Template
  513 + * \note \ref input_string_buffer
508 */ 514 */
509 -BR_EXPORT const char* br_get_filename(br_template tmpl); 515 +BR_EXPORT int br_get_filename(br_template tmpl, char * buffer, int buffer_length);
510 /*! 516 /*!
511 * \brief Set the filename for a br::Template. 517 * \brief Set the filename for a br::Template.
512 */ 518 */
513 BR_EXPORT void br_set_filename(br_template tmpl, const char *filename); 519 BR_EXPORT void br_set_filename(br_template tmpl, const char *filename);
514 /*! 520 /*!
515 * \brief Get metadata as a string for the given key in the given template. 521 * \brief Get metadata as a string for the given key in the given template.
  522 + * \note \ref input_string_buffer
516 */ 523 */
517 -BR_EXPORT const char* br_get_metadata_string(br_template, const char *key); 524 +BR_EXPORT int br_get_metadata_string(br_template, const char *key, char * buffer, int buffer_length);
518 /*! 525 /*!
519 * \brief Enroll a br::Template from the C API! Returns a pointer to a br::TemplateList 526 * \brief Enroll a br::Template from the C API! Returns a pointer to a br::TemplateList
520 * \param tmpl Pointer to a br::Template. 527 * \param tmpl Pointer to a br::Template.
openbr/openbr_plugin.cpp
@@ -203,6 +203,13 @@ QList&lt;QRectF&gt; File::namedRects() const @@ -203,6 +203,13 @@ QList&lt;QRectF&gt; File::namedRects() const
203 const QVariant &variant = m_metadata[key]; 203 const QVariant &variant = m_metadata[key];
204 if (variant.canConvert<QRectF>()) 204 if (variant.canConvert<QRectF>())
205 rects.append(variant.value<QRectF>()); 205 rects.append(variant.value<QRectF>());
  206 + else if(variant.canConvert<QList<QRectF> >()) {
  207 + QList<QRectF> list = variant.value<QList<QRectF> >();
  208 + for (int i=0;i < list.size();i++)
  209 + {
  210 + rects.append(list[i]);
  211 + }
  212 + }
206 } 213 }
207 return rects; 214 return rects;
208 } 215 }
@@ -1009,6 +1016,47 @@ QString br::Context::scratchPath() @@ -1009,6 +1016,47 @@ QString br::Context::scratchPath()
1009 return QString("%1/%2-%3.%4").arg(QDir::homePath(), PRODUCT_NAME, QString::number(PRODUCT_VERSION_MAJOR), QString::number(PRODUCT_VERSION_MINOR)); 1016 return QString("%1/%2-%3.%4").arg(QDir::homePath(), PRODUCT_NAME, QString::number(PRODUCT_VERSION_MAJOR), QString::number(PRODUCT_VERSION_MINOR));
1010 } 1017 }
1011 1018
  1019 +
  1020 +QStringList br::Context::objects(const char *abstractions, const char *implementations, bool parameters)
  1021 +{
  1022 + QStringList objectList;
  1023 + QRegExp abstractionsRegExp(abstractions);
  1024 + QRegExp implementationsRegExp(implementations);
  1025 +
  1026 + if (abstractionsRegExp.exactMatch("Abbreviation"))
  1027 + foreach (const QString &name, Globals->abbreviations.keys())
  1028 + if (implementationsRegExp.exactMatch(name))
  1029 + objectList.append(name + (parameters ? "\t" + Globals->abbreviations[name] : ""));
  1030 +
  1031 + if (abstractionsRegExp.exactMatch("Distance"))
  1032 + foreach (const QString &name, Factory<Distance>::names())
  1033 + if (implementationsRegExp.exactMatch(name))
  1034 + objectList.append(name + (parameters ? "\t" + Factory<Distance>::parameters(name) : ""));
  1035 +
  1036 + if (abstractionsRegExp.exactMatch("Format"))
  1037 + foreach (const QString &name, Factory<Format>::names())
  1038 + if (implementationsRegExp.exactMatch(name))
  1039 + objectList.append(name + (parameters ? "\t" + Factory<Format>::parameters(name) : ""));
  1040 +
  1041 + if (abstractionsRegExp.exactMatch("Initializer"))
  1042 + foreach (const QString &name, Factory<Initializer>::names())
  1043 + if (implementationsRegExp.exactMatch(name))
  1044 + objectList.append(name + (parameters ? "\t" + Factory<Initializer>::parameters(name) : ""));
  1045 +
  1046 + if (abstractionsRegExp.exactMatch("Output"))
  1047 + foreach (const QString &name, Factory<Output>::names())
  1048 + if (implementationsRegExp.exactMatch(name))
  1049 + objectList.append(name + (parameters ? "\t" + Factory<Output>::parameters(name) : ""));
  1050 +
  1051 + if (abstractionsRegExp.exactMatch("Transform"))
  1052 + foreach (const QString &name, Factory<Transform>::names())
  1053 + if (implementationsRegExp.exactMatch(name))
  1054 + objectList.append(name + (parameters ? "\t" + Factory<Transform>::parameters(name) : ""));
  1055 +
  1056 +
  1057 + return objectList;
  1058 +}
  1059 +
1012 void br::Context::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) 1060 void br::Context::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
1013 { 1061 {
1014 // Something about this method is not thread safe, and will lead to crashes if qDebug 1062 // Something about this method is not thread safe, and will lead to crashes if qDebug
openbr/openbr_plugin.h
@@ -830,6 +830,18 @@ public: @@ -830,6 +830,18 @@ public:
830 */ 830 */
831 static QString scratchPath(); 831 static QString scratchPath();
832 832
  833 + /*!
  834 + * \brief Returns names and parameters for the requested objects.
  835 + *
  836 + * Each object is \c \\n seperated. Arguments are seperated from the object name with a \c \\t.
  837 + * \param abstractions Regular expression of the abstractions to search.
  838 + * \param implementations Regular expression of the implementations to search.
  839 + * \param parameters Include parameters after object name.
  840 + * \note \ref managed_return_value
  841 + * \note This function uses Qt's <a href="http://doc.qt.digia.com/stable/qregexp.html">QRegExp</a> syntax.
  842 + */
  843 + static QStringList objects(const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true);
  844 +
833 private: 845 private:
834 static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); 846 static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
835 }; 847 };