diff --git a/app/br/br.cpp b/app/br/br.cpp index abeeab1..e78c71d 100644 --- a/app/br/br.cpp +++ b/app/br/br.cpp @@ -171,7 +171,11 @@ public: // Do nothing because we checked for this flag prior to initialization } else if (!strcmp(fun, "objects")) { check(parc <= 2, "Incorrect parameter count for 'objects'."); - printf("%s\n", br_objects(parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*")); + int size = br_objects(NULL, 0, parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*"); + char * temp = new char[size]; + br_objects(temp, size, parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*"); + printf("%s\n", temp); + delete [] temp; } else if (!strcmp(fun, "about")) { check(parc == 0, "No parameters expected for 'about'."); printf("%s\n", br_about()); diff --git a/openbr/gui/algorithm.cpp b/openbr/gui/algorithm.cpp index 39fe742..dbce8dd 100644 --- a/openbr/gui/algorithm.cpp +++ b/openbr/gui/algorithm.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "algorithm.h" @@ -18,7 +19,7 @@ bool br::Algorithm::addAlgorithm(const QString &algorithm, const QString &displa { static QStringList availableAlgorithms; if (availableAlgorithms.isEmpty()) - availableAlgorithms = QString(br_objects("Abbreviation", ".*", false)).split("\n"); + availableAlgorithms = br::Context::objects("Abbreviation", ".*", false); if (!availableAlgorithms.contains(algorithm)) return false; diff --git a/openbr/gui/gallerytoolbar.cpp b/openbr/gui/gallerytoolbar.cpp index 7b6dde4..673e60f 100644 --- a/openbr/gui/gallerytoolbar.cpp +++ b/openbr/gui/gallerytoolbar.cpp @@ -84,7 +84,7 @@ void br::GalleryToolBar::_enroll(const br::File &input) galleryLock.lock(); this->input = input; if (input.suffix() == "gal") gallery = input.name + ".mem"; - else gallery = QString("%1/galleries/%2.gal[cache]").arg(br_scratch_path(), qPrintable(input.baseName()+input.hash())); + else gallery = QString("%1/galleries/%2.gal[cache]").arg(br::Globals->scratchPath(), qPrintable(input.baseName()+input.hash())); files = br::Enroll(input.flat(), gallery.flat()); galleryLock.unlock(); } @@ -148,7 +148,7 @@ void br::GalleryToolBar::home() void br::GalleryToolBar::mean() { - const QString file = QString("%1/mean/%2.png").arg(br_scratch_path(), input.baseName()+input.hash()); + const QString file = QString("%1/mean/%2.png").arg(br::Globals->scratchPath(), input.baseName()+input.hash()); br_set_property("CENTER_TRAIN_B", qPrintable(file)); br::File trainingFile = input; br_train(qPrintable(trainingFile.flat()), "[algorithm=MedianFace]"); diff --git a/openbr/gui/progress.cpp b/openbr/gui/progress.cpp index c162b5d..482367b 100644 --- a/openbr/gui/progress.cpp +++ b/openbr/gui/progress.cpp @@ -1,4 +1,5 @@ #include +#include #include "progress.h" @@ -29,7 +30,7 @@ void br::Progress::checkProgress() const bool visible = progress >= 0 && progress < 100; if (visible) { - showMessage(br_most_recent_message()); + showMessage(Globals->mostRecentMessage); pbProgress.setValue(progress); if (progress > 100) pbProgress.setMaximum(0); else pbProgress.setMaximum(100); diff --git a/openbr/gui/templateviewer.cpp b/openbr/gui/templateviewer.cpp index a811cb2..56ab028 100644 --- a/openbr/gui/templateviewer.cpp +++ b/openbr/gui/templateviewer.cpp @@ -72,7 +72,7 @@ void TemplateViewer::refreshImage() if (file.isNull() || (format == "Photo")) { setImage(file, true); } else { - const QString path = QString(br_scratch_path()) + "/thumbnails"; + const QString path = QString(br::Globals->scratchPath()) + "/thumbnails"; const QString hash = file.hash()+format; const QString processedFile = path+"/"+file.baseName()+hash+".png"; if (!QFileInfo(processedFile).exists()) { diff --git a/openbr/gui/transformeditor.cpp b/openbr/gui/transformeditor.cpp index 4f2752a..c679e4e 100644 --- a/openbr/gui/transformeditor.cpp +++ b/openbr/gui/transformeditor.cpp @@ -24,7 +24,7 @@ using namespace br; br::TransformEditor::TransformEditor(Transform *transform, QWidget *parent) : QWidget(parent) { - name.addItems(QString(br_objects("Transform", ".*", false)).split('\n')); + name.addItems(br::Context::objects("Transform", ".*", false)); layout.addWidget(&name); setLayout(&layout); diff --git a/openbr/openbr.cpp b/openbr/openbr.cpp index 09f0163..2c3bd79 100644 --- a/openbr/openbr.cpp +++ b/openbr/openbr.cpp @@ -28,6 +28,21 @@ using namespace br; +static int partialCopy(const QString & string, char * buffer, int buffer_length) +{ + + QByteArray byteArray = string.toLocal8Bit(); + + int copyLength = std::min(buffer_length-1, byteArray.size()); + if (copyLength < 0) + return byteArray.size() + 1; + + memcpy(buffer, byteArray.data(), copyLength); + buffer[copyLength] = '\0'; + + return byteArray.size() + 1; +} + const char *br_about() { static QMutex aboutLock; @@ -153,53 +168,14 @@ void br_make_pairwise_mask(const char *target_input, const char *query_input, co BEE::makePairwiseMask(target_input, query_input, mask); } -const char *br_most_recent_message() +int br_most_recent_message(char * buffer, int buffer_length) { - static QByteArray byteArray; - byteArray = Globals->mostRecentMessage.toLocal8Bit(); - return byteArray.data(); + return partialCopy(Globals->mostRecentMessage, buffer, buffer_length); } -const char *br_objects(const char *abstractions, const char *implementations, bool parameters) +int br_objects(char * buffer, int buffer_length, const char *abstractions, const char *implementations, bool parameters) { - static QByteArray objects; - - QStringList objectList; - QRegExp abstractionsRegExp(abstractions); - QRegExp implementationsRegExp(implementations); - - if (abstractionsRegExp.exactMatch("Abbreviation")) - foreach (const QString &name, Globals->abbreviations.keys()) - if (implementationsRegExp.exactMatch(name)) - objectList.append(name + (parameters ? "\t" + Globals->abbreviations[name] : "")); - - if (abstractionsRegExp.exactMatch("Distance")) - foreach (const QString &name, Factory::names()) - if (implementationsRegExp.exactMatch(name)) - objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); - - if (abstractionsRegExp.exactMatch("Format")) - foreach (const QString &name, Factory::names()) - if (implementationsRegExp.exactMatch(name)) - objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); - - if (abstractionsRegExp.exactMatch("Initializer")) - foreach (const QString &name, Factory::names()) - if (implementationsRegExp.exactMatch(name)) - objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); - - if (abstractionsRegExp.exactMatch("Output")) - foreach (const QString &name, Factory::names()) - if (implementationsRegExp.exactMatch(name)) - objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); - - if (abstractionsRegExp.exactMatch("Transform")) - foreach (const QString &name, Factory::names()) - if (implementationsRegExp.exactMatch(name)) - objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); - - objects = objectList.join("\n").toLocal8Bit(); - return objects.data(); + return partialCopy(br::Context::objects(abstractions, implementations, parameters).join('\n'), buffer, buffer_length); } 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) *argv = rawCharArrayList.data(); } -const char *br_scratch_path() +int br_scratch_path(char * buffer, int buffer_length) { - static QByteArray byteArray; - byteArray = Context::scratchPath().toLocal8Bit(); - return byteArray.data(); + return partialCopy(Context::scratchPath(), buffer, buffer_length); } const char *br_sdk_path() @@ -387,11 +361,9 @@ bool br_img_is_empty(br_template tmpl) return t->m().empty(); } -const char* br_get_filename(br_template tmpl) +int br_get_filename(br_template tmpl, char * buffer, int buffer_length) { - static QByteArray buffer; - buffer = reinterpret_cast(tmpl)->file.name.toLocal8Bit(); - return buffer.data(); + return partialCopy(reinterpret_cast(tmpl)->file.name, buffer, buffer_length); } void br_set_filename(br_template tmpl, const char *filename) @@ -400,15 +372,11 @@ void br_set_filename(br_template tmpl, const char *filename) t->file.name = filename; } -const char* br_get_metadata_string(br_template tmpl, const char *key) +int br_get_metadata_string(br_template tmpl, const char *key, char * buffer, int buffer_length) { Template *t = reinterpret_cast(tmpl); - // need an object outside of this scope - // so the char pointer is valid - static QByteArray result; QVariant qvar = t->file.value(key); - result = QtUtils::toString(qvar).toUtf8(); - return result.data(); + return partialCopy(QtUtils::toString(qvar), buffer, buffer_length); } br_template_list br_enroll_template(br_template tmpl) diff --git a/openbr/openbr.h b/openbr/openbr.h index 12e4af8..4438b27 100644 --- a/openbr/openbr.h +++ b/openbr/openbr.h @@ -41,6 +41,10 @@ extern "C" { * \section managed_return_value Managed Return Value * Memory for const char* return values is managed internally and guaranteed until the next call to the function. * + * \section input_string_buffer Input String Buffer + * 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 + * small, only part of the string will be copied. Returns the buffer size required to contain the complete string. + * * \section examples Examples * - \ref c_face_recognition_evaluation * @@ -255,10 +259,10 @@ BR_EXPORT void br_make_pairwise_mask(const char *target_input, const char *query /*! * \brief Returns the most recent line sent to stderr. - * \note \ref managed_return_value + * \note \ref input_string_buffer * \see br_progress br_time_remaining */ -BR_EXPORT const char *br_most_recent_message(); +BR_EXPORT int br_most_recent_message(char * buffer, int buffer_length); /*! * \brief Returns names and parameters for the requested objects. @@ -267,10 +271,10 @@ BR_EXPORT const char *br_most_recent_message(); * \param abstractions Regular expression of the abstractions to search. * \param implementations Regular expression of the implementations to search. * \param parameters Include parameters after object name. - * \note \ref managed_return_value + * \note \ref input_string_buffer * \note This function uses Qt's QRegExp syntax. */ -BR_EXPORT const char *br_objects(const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true); +BR_EXPORT int br_objects(char * buffer, int buffer_length, const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true); /*! * \brief Renders recognition performance figures for a set of .csv files created by \ref br_eval. @@ -375,9 +379,11 @@ BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv); /*! * \brief Wraps br::Context::scratchPath() + * \note \ref input_string_buffer * \see br_version */ -BR_EXPORT const char *br_scratch_path(); +BR_EXPORT int br_scratch_path(char * buffer, int buffer_length); + /*! * \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 /*! * \brief Wraps br::Context::version() - * \note \ref managed_return_value * \see br_about br_scratch_path */ BR_EXPORT const char *br_version(); @@ -505,16 +510,18 @@ BR_EXPORT int br_img_channels(br_template tmpl); BR_EXPORT bool br_img_is_empty(br_template tmpl); /*! * \brief Get the filename for a br::Template + * \note \ref input_string_buffer */ -BR_EXPORT const char* br_get_filename(br_template tmpl); +BR_EXPORT int br_get_filename(br_template tmpl, char * buffer, int buffer_length); /*! * \brief Set the filename for a br::Template. */ BR_EXPORT void br_set_filename(br_template tmpl, const char *filename); /*! * \brief Get metadata as a string for the given key in the given template. + * \note \ref input_string_buffer */ -BR_EXPORT const char* br_get_metadata_string(br_template, const char *key); +BR_EXPORT int br_get_metadata_string(br_template, const char *key, char * buffer, int buffer_length); /*! * \brief Enroll a br::Template from the C API! Returns a pointer to a br::TemplateList * \param tmpl Pointer to a br::Template. diff --git a/openbr/openbr_plugin.cpp b/openbr/openbr_plugin.cpp index 283ec09..1740bde 100644 --- a/openbr/openbr_plugin.cpp +++ b/openbr/openbr_plugin.cpp @@ -203,6 +203,13 @@ QList File::namedRects() const const QVariant &variant = m_metadata[key]; if (variant.canConvert()) rects.append(variant.value()); + else if(variant.canConvert >()) { + QList list = variant.value >(); + for (int i=0;i < list.size();i++) + { + rects.append(list[i]); + } + } } return rects; } @@ -1009,6 +1016,47 @@ QString br::Context::scratchPath() return QString("%1/%2-%3.%4").arg(QDir::homePath(), PRODUCT_NAME, QString::number(PRODUCT_VERSION_MAJOR), QString::number(PRODUCT_VERSION_MINOR)); } + +QStringList br::Context::objects(const char *abstractions, const char *implementations, bool parameters) +{ + QStringList objectList; + QRegExp abstractionsRegExp(abstractions); + QRegExp implementationsRegExp(implementations); + + if (abstractionsRegExp.exactMatch("Abbreviation")) + foreach (const QString &name, Globals->abbreviations.keys()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Globals->abbreviations[name] : "")); + + if (abstractionsRegExp.exactMatch("Distance")) + foreach (const QString &name, Factory::names()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); + + if (abstractionsRegExp.exactMatch("Format")) + foreach (const QString &name, Factory::names()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); + + if (abstractionsRegExp.exactMatch("Initializer")) + foreach (const QString &name, Factory::names()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); + + if (abstractionsRegExp.exactMatch("Output")) + foreach (const QString &name, Factory::names()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); + + if (abstractionsRegExp.exactMatch("Transform")) + foreach (const QString &name, Factory::names()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); + + + return objectList; +} + void br::Context::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { // Something about this method is not thread safe, and will lead to crashes if qDebug diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index e6f2850..3f84d7e 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -830,6 +830,18 @@ public: */ static QString scratchPath(); + /*! + * \brief Returns names and parameters for the requested objects. + * + * Each object is \c \\n seperated. Arguments are seperated from the object name with a \c \\t. + * \param abstractions Regular expression of the abstractions to search. + * \param implementations Regular expression of the implementations to search. + * \param parameters Include parameters after object name. + * \note \ref managed_return_value + * \note This function uses Qt's QRegExp syntax. + */ + static QStringList objects(const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true); + private: static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); };