Commit a232dceb21a97cc3077f83c58aae0e5274b60969
Merge pull request #164 from biometrics/string_management
Updates to the c API to handle returning strings more safely
Showing
11 changed files
with
148 additions
and
83 deletions
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 &algorithm, const QString &displa | @@ -18,7 +19,7 @@ bool br::Algorithm::addAlgorithm(const QString &algorithm, const QString &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 &input) | @@ -84,7 +84,7 @@ void br::GalleryToolBar::_enroll(const br::File &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,9 +28,27 @@ | @@ -28,9 +28,27 @@ | ||
| 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 | { |
| 48 | + static QMutex aboutLock; | ||
| 49 | + QMutexLocker lock(&aboutLock); | ||
| 33 | static QByteArray about = Context::about().toLocal8Bit(); | 50 | static QByteArray about = Context::about().toLocal8Bit(); |
| 51 | + | ||
| 34 | return about.data(); | 52 | return about.data(); |
| 35 | } | 53 | } |
| 36 | 54 | ||
| @@ -150,53 +168,14 @@ void br_make_pairwise_mask(const char *target_input, const char *query_input, co | @@ -150,53 +168,14 @@ void br_make_pairwise_mask(const char *target_input, const char *query_input, co | ||
| 150 | BEE::makePairwiseMask(target_input, query_input, mask); | 168 | BEE::makePairwiseMask(target_input, query_input, mask); |
| 151 | } | 169 | } |
| 152 | 170 | ||
| 153 | -const char *br_most_recent_message() | 171 | +int br_most_recent_message(char * buffer, int buffer_length) |
| 154 | { | 172 | { |
| 155 | - static QByteArray byteArray; | ||
| 156 | - byteArray = Globals->mostRecentMessage.toLocal8Bit(); | ||
| 157 | - return byteArray.data(); | 173 | + return partialCopy(Globals->mostRecentMessage, buffer, buffer_length); |
| 158 | } | 174 | } |
| 159 | 175 | ||
| 160 | -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) |
| 161 | { | 177 | { |
| 162 | - static QByteArray objects; | ||
| 163 | - | ||
| 164 | - QStringList objectList; | ||
| 165 | - QRegExp abstractionsRegExp(abstractions); | ||
| 166 | - QRegExp implementationsRegExp(implementations); | ||
| 167 | - | ||
| 168 | - if (abstractionsRegExp.exactMatch("Abbreviation")) | ||
| 169 | - foreach (const QString &name, Globals->abbreviations.keys()) | ||
| 170 | - if (implementationsRegExp.exactMatch(name)) | ||
| 171 | - objectList.append(name + (parameters ? "\t" + Globals->abbreviations[name] : "")); | ||
| 172 | - | ||
| 173 | - if (abstractionsRegExp.exactMatch("Distance")) | ||
| 174 | - foreach (const QString &name, Factory<Distance>::names()) | ||
| 175 | - if (implementationsRegExp.exactMatch(name)) | ||
| 176 | - objectList.append(name + (parameters ? "\t" + Factory<Distance>::parameters(name) : "")); | ||
| 177 | - | ||
| 178 | - if (abstractionsRegExp.exactMatch("Format")) | ||
| 179 | - foreach (const QString &name, Factory<Format>::names()) | ||
| 180 | - if (implementationsRegExp.exactMatch(name)) | ||
| 181 | - objectList.append(name + (parameters ? "\t" + Factory<Format>::parameters(name) : "")); | ||
| 182 | - | ||
| 183 | - if (abstractionsRegExp.exactMatch("Initializer")) | ||
| 184 | - foreach (const QString &name, Factory<Initializer>::names()) | ||
| 185 | - if (implementationsRegExp.exactMatch(name)) | ||
| 186 | - objectList.append(name + (parameters ? "\t" + Factory<Initializer>::parameters(name) : "")); | ||
| 187 | - | ||
| 188 | - if (abstractionsRegExp.exactMatch("Output")) | ||
| 189 | - foreach (const QString &name, Factory<Output>::names()) | ||
| 190 | - if (implementationsRegExp.exactMatch(name)) | ||
| 191 | - objectList.append(name + (parameters ? "\t" + Factory<Output>::parameters(name) : "")); | ||
| 192 | - | ||
| 193 | - if (abstractionsRegExp.exactMatch("Transform")) | ||
| 194 | - foreach (const QString &name, Factory<Transform>::names()) | ||
| 195 | - if (implementationsRegExp.exactMatch(name)) | ||
| 196 | - objectList.append(name + (parameters ? "\t" + Factory<Transform>::parameters(name) : "")); | ||
| 197 | - | ||
| 198 | - objects = objectList.join("\n").toLocal8Bit(); | ||
| 199 | - return objects.data(); | 178 | + return partialCopy(br::Context::objects(abstractions, implementations, parameters).join('\n'), buffer, buffer_length); |
| 200 | } | 179 | } |
| 201 | 180 | ||
| 202 | 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) |
| @@ -251,15 +230,15 @@ void br_read_pipe(const char *pipe, int *argc, char ***argv) | @@ -251,15 +230,15 @@ void br_read_pipe(const char *pipe, int *argc, char ***argv) | ||
| 251 | *argv = rawCharArrayList.data(); | 230 | *argv = rawCharArrayList.data(); |
| 252 | } | 231 | } |
| 253 | 232 | ||
| 254 | -const char *br_scratch_path() | 233 | +int br_scratch_path(char * buffer, int buffer_length) |
| 255 | { | 234 | { |
| 256 | - static QByteArray byteArray; | ||
| 257 | - byteArray = Context::scratchPath().toLocal8Bit(); | ||
| 258 | - return byteArray.data(); | 235 | + return partialCopy(Context::scratchPath(), buffer, buffer_length); |
| 259 | } | 236 | } |
| 260 | 237 | ||
| 261 | const char *br_sdk_path() | 238 | const char *br_sdk_path() |
| 262 | { | 239 | { |
| 240 | + static QMutex sdkLock; | ||
| 241 | + QMutexLocker lock(&sdkLock); | ||
| 263 | static QByteArray sdkPath = QDir(Globals->sdkPath).absolutePath().toLocal8Bit(); | 242 | static QByteArray sdkPath = QDir(Globals->sdkPath).absolutePath().toLocal8Bit(); |
| 264 | return sdkPath.data(); | 243 | return sdkPath.data(); |
| 265 | } | 244 | } |
| @@ -303,6 +282,8 @@ void br_train_n(int num_inputs, const char *inputs[], const char *model) | @@ -303,6 +282,8 @@ void br_train_n(int num_inputs, const char *inputs[], const char *model) | ||
| 303 | 282 | ||
| 304 | const char *br_version() | 283 | const char *br_version() |
| 305 | { | 284 | { |
| 285 | + static QMutex versionLock; | ||
| 286 | + QMutexLocker lock(&versionLock); | ||
| 306 | static QByteArray version = Context::version().toLocal8Bit(); | 287 | static QByteArray version = Context::version().toLocal8Bit(); |
| 307 | return version.data(); | 288 | return version.data(); |
| 308 | } | 289 | } |
| @@ -380,11 +361,9 @@ bool br_img_is_empty(br_template tmpl) | @@ -380,11 +361,9 @@ bool br_img_is_empty(br_template tmpl) | ||
| 380 | return t->m().empty(); | 361 | return t->m().empty(); |
| 381 | } | 362 | } |
| 382 | 363 | ||
| 383 | -const char* br_get_filename(br_template tmpl) | 364 | +int br_get_filename(char * buffer, int buffer_length, br_template tmpl) |
| 384 | { | 365 | { |
| 385 | - static QByteArray buffer; | ||
| 386 | - buffer = reinterpret_cast<Template*>(tmpl)->file.name.toLocal8Bit(); | ||
| 387 | - return buffer.data(); | 366 | + return partialCopy(reinterpret_cast<Template*>(tmpl)->file.name, buffer, buffer_length); |
| 388 | } | 367 | } |
| 389 | 368 | ||
| 390 | void br_set_filename(br_template tmpl, const char *filename) | 369 | void br_set_filename(br_template tmpl, const char *filename) |
| @@ -393,15 +372,11 @@ void br_set_filename(br_template tmpl, const char *filename) | @@ -393,15 +372,11 @@ void br_set_filename(br_template tmpl, const char *filename) | ||
| 393 | t->file.name = filename; | 372 | t->file.name = filename; |
| 394 | } | 373 | } |
| 395 | 374 | ||
| 396 | -const char* br_get_metadata_string(br_template tmpl, const char *key) | 375 | +int br_get_metadata_string(char * buffer, int buffer_length, br_template tmpl, const char *key) |
| 397 | { | 376 | { |
| 398 | Template *t = reinterpret_cast<Template*>(tmpl); | 377 | Template *t = reinterpret_cast<Template*>(tmpl); |
| 399 | - // need an object outside of this scope | ||
| 400 | - // so the char pointer is valid | ||
| 401 | - static QByteArray result; | ||
| 402 | QVariant qvar = t->file.value(key); | 378 | QVariant qvar = t->file.value(key); |
| 403 | - result = QtUtils::toString(qvar).toUtf8(); | ||
| 404 | - return result.data(); | 379 | + return partialCopy(QtUtils::toString(qvar), buffer, buffer_length); |
| 405 | } | 380 | } |
| 406 | 381 | ||
| 407 | 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 "C" { | @@ -41,6 +41,10 @@ extern "C" { | ||
| 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 | * |
| @@ -56,7 +60,6 @@ extern "C" { | @@ -56,7 +60,6 @@ extern "C" { | ||
| 56 | 60 | ||
| 57 | /*! | 61 | /*! |
| 58 | * \brief Wraps br::Context::about() | 62 | * \brief Wraps br::Context::about() |
| 59 | - * \note \ref managed_return_value | ||
| 60 | * \see br_version | 63 | * \see br_version |
| 61 | */ | 64 | */ |
| 62 | BR_EXPORT const char *br_about(); | 65 | BR_EXPORT const char *br_about(); |
| @@ -256,10 +259,10 @@ BR_EXPORT void br_make_pairwise_mask(const char *target_input, const char *query | @@ -256,10 +259,10 @@ BR_EXPORT void br_make_pairwise_mask(const char *target_input, const char *query | ||
| 256 | 259 | ||
| 257 | /*! | 260 | /*! |
| 258 | * \brief Returns the most recent line sent to stderr. | 261 | * \brief Returns the most recent line sent to stderr. |
| 259 | - * \note \ref managed_return_value | 262 | + * \note \ref input_string_buffer |
| 260 | * \see br_progress br_time_remaining | 263 | * \see br_progress br_time_remaining |
| 261 | */ | 264 | */ |
| 262 | -BR_EXPORT const char *br_most_recent_message(); | 265 | +BR_EXPORT int br_most_recent_message(char * buffer, int buffer_length); |
| 263 | 266 | ||
| 264 | /*! | 267 | /*! |
| 265 | * \brief Returns names and parameters for the requested objects. | 268 | * \brief Returns names and parameters for the requested objects. |
| @@ -268,10 +271,10 @@ BR_EXPORT const char *br_most_recent_message(); | @@ -268,10 +271,10 @@ BR_EXPORT const char *br_most_recent_message(); | ||
| 268 | * \param abstractions Regular expression of the abstractions to search. | 271 | * \param abstractions Regular expression of the abstractions to search. |
| 269 | * \param implementations Regular expression of the implementations to search. | 272 | * \param implementations Regular expression of the implementations to search. |
| 270 | * \param parameters Include parameters after object name. | 273 | * \param parameters Include parameters after object name. |
| 271 | - * \note \ref managed_return_value | 274 | + * \note \ref input_string_buffer |
| 272 | * \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. |
| 273 | */ | 276 | */ |
| 274 | -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); |
| 275 | 278 | ||
| 276 | /*! | 279 | /*! |
| 277 | * \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. |
| @@ -376,14 +379,14 @@ BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv); | @@ -376,14 +379,14 @@ BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv); | ||
| 376 | 379 | ||
| 377 | /*! | 380 | /*! |
| 378 | * \brief Wraps br::Context::scratchPath() | 381 | * \brief Wraps br::Context::scratchPath() |
| 379 | - * \note \ref managed_return_value | 382 | + * \note \ref input_string_buffer |
| 380 | * \see br_version | 383 | * \see br_version |
| 381 | */ | 384 | */ |
| 382 | -BR_EXPORT const char *br_scratch_path(); | 385 | +BR_EXPORT int br_scratch_path(char * buffer, int buffer_length); |
| 386 | + | ||
| 383 | 387 | ||
| 384 | /*! | 388 | /*! |
| 385 | * \brief Returns the full path to the root of the SDK. | 389 | * \brief Returns the full path to the root of the SDK. |
| 386 | - * \note \ref managed_return_value | ||
| 387 | * \see br_initialize | 390 | * \see br_initialize |
| 388 | */ | 391 | */ |
| 389 | BR_EXPORT const char *br_sdk_path(); | 392 | BR_EXPORT const char *br_sdk_path(); |
| @@ -436,7 +439,6 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode | @@ -436,7 +439,6 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode | ||
| 436 | 439 | ||
| 437 | /*! | 440 | /*! |
| 438 | * \brief Wraps br::Context::version() | 441 | * \brief Wraps br::Context::version() |
| 439 | - * \note \ref managed_return_value | ||
| 440 | * \see br_about br_scratch_path | 442 | * \see br_about br_scratch_path |
| 441 | */ | 443 | */ |
| 442 | BR_EXPORT const char *br_version(); | 444 | BR_EXPORT const char *br_version(); |
| @@ -508,16 +510,18 @@ BR_EXPORT int br_img_channels(br_template tmpl); | @@ -508,16 +510,18 @@ BR_EXPORT int br_img_channels(br_template tmpl); | ||
| 508 | BR_EXPORT bool br_img_is_empty(br_template tmpl); | 510 | BR_EXPORT bool br_img_is_empty(br_template tmpl); |
| 509 | /*! | 511 | /*! |
| 510 | * \brief Get the filename for a br::Template | 512 | * \brief Get the filename for a br::Template |
| 513 | + * \note \ref input_string_buffer | ||
| 511 | */ | 514 | */ |
| 512 | -BR_EXPORT const char* br_get_filename(br_template tmpl); | 515 | +BR_EXPORT int br_get_filename(char * buffer, int buffer_length, br_template tmpl); |
| 513 | /*! | 516 | /*! |
| 514 | * \brief Set the filename for a br::Template. | 517 | * \brief Set the filename for a br::Template. |
| 515 | */ | 518 | */ |
| 516 | 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); |
| 517 | /*! | 520 | /*! |
| 518 | * \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 | ||
| 519 | */ | 523 | */ |
| 520 | -BR_EXPORT const char* br_get_metadata_string(br_template, const char *key); | 524 | +BR_EXPORT int br_get_metadata_string(char * buffer, int buffer_length, br_template tmpl, const char *key); |
| 521 | /*! | 525 | /*! |
| 522 | * \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 |
| 523 | * \param tmpl Pointer to a br::Template. | 527 | * \param tmpl Pointer to a br::Template. |
openbr/openbr_plugin.cpp
| @@ -203,6 +203,13 @@ QList<QRectF> File::namedRects() const | @@ -203,6 +203,13 @@ QList<QRectF> 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 | }; |
scripts/brpy/__init__.py
| @@ -12,6 +12,14 @@ def _var_string_args(n): | @@ -12,6 +12,14 @@ def _var_string_args(n): | ||
| 12 | s.extend(_string_args(n)) | 12 | s.extend(_string_args(n)) |
| 13 | return s | 13 | return s |
| 14 | 14 | ||
| 15 | +def _handle_string_func(func): | ||
| 16 | + def call_func(*args): | ||
| 17 | + howlong = func('', 0, *args) | ||
| 18 | + msg = 'x'*(howlong-1) | ||
| 19 | + func(msg, howlong, *args) | ||
| 20 | + return msg | ||
| 21 | + return call_func | ||
| 22 | + | ||
| 15 | def init_brpy(br_loc='/usr/local/lib'): | 23 | def init_brpy(br_loc='/usr/local/lib'): |
| 16 | """Takes the ctypes lib object for br and initializes all function inputs and outputs""" | 24 | """Takes the ctypes lib object for br and initializes all function inputs and outputs""" |
| 17 | br_loc += '/libopenbr.%s' | 25 | br_loc += '/libopenbr.%s' |
| @@ -48,9 +56,14 @@ def init_brpy(br_loc='/usr/local/lib'): | @@ -48,9 +56,14 @@ def init_brpy(br_loc='/usr/local/lib'): | ||
| 48 | br.br_is_classifier.restype = c_bool | 56 | br.br_is_classifier.restype = c_bool |
| 49 | br.br_make_mask.argtypes = _string_args(3) | 57 | br.br_make_mask.argtypes = _string_args(3) |
| 50 | br.br_make_pairwise_mask.argtypes = _string_args(3) | 58 | br.br_make_pairwise_mask.argtypes = _string_args(3) |
| 51 | - br.br_most_recent_message.restype = c_char_p | ||
| 52 | - br.br_objects.argtypes = _string_args(2) + [c_bool] | ||
| 53 | - br.br_objects.restype = c_char_p | 59 | + br.br_most_recent_message.argtypes = [c_char_p, c_int] |
| 60 | + br.br_most_recent_message.restype = c_int | ||
| 61 | + func = br.br_most_recent_message.__call__ | ||
| 62 | + br.br_most_recent_message = _handle_string_func(func) | ||
| 63 | + br.br_objects.argtypes = [c_char_p, c_int] + _string_args(2) + [c_bool] | ||
| 64 | + br.br_objects.restype = c_int | ||
| 65 | + func2 = br.br_objects.__call__ | ||
| 66 | + br.br_objects = _handle_string_func(func2) | ||
| 54 | br.br_plot.argtypes = plot_args | 67 | br.br_plot.argtypes = plot_args |
| 55 | br.br_plot.restype = c_bool | 68 | br.br_plot.restype = c_bool |
| 56 | br.br_plot_detection.argtypes = plot_args | 69 | br.br_plot_detection.argtypes = plot_args |
| @@ -61,7 +74,10 @@ def init_brpy(br_loc='/usr/local/lib'): | @@ -61,7 +74,10 @@ def init_brpy(br_loc='/usr/local/lib'): | ||
| 61 | br.br_plot_metadata.restype = c_bool | 74 | br.br_plot_metadata.restype = c_bool |
| 62 | br.br_progress.restype = c_float | 75 | br.br_progress.restype = c_float |
| 63 | br.br_read_pipe.argtypes = [c_char_p, POINTER(c_int), POINTER(POINTER(c_char_p))] | 76 | br.br_read_pipe.argtypes = [c_char_p, POINTER(c_int), POINTER(POINTER(c_char_p))] |
| 64 | - br.br_scratch_path.restype = c_char_p | 77 | + br.br_scratch_path.argtypes = [c_char_p, c_int] |
| 78 | + br.br_scratch_path.restype = c_int | ||
| 79 | + func3 = br.br_scratch_path.__call__ | ||
| 80 | + br.br_scratch_path = _handle_string_func(func3) | ||
| 65 | br.br_sdk_path.restype = c_char_p | 81 | br.br_sdk_path.restype = c_char_p |
| 66 | br.br_get_header.argtypes = [c_char_p, POINTER(c_char_p), POINTER(c_char_p)] | 82 | br.br_get_header.argtypes = [c_char_p, POINTER(c_char_p), POINTER(c_char_p)] |
| 67 | br.br_set_header.argtypes = _string_args(3) | 83 | br.br_set_header.argtypes = _string_args(3) |
| @@ -88,11 +104,15 @@ def init_brpy(br_loc='/usr/local/lib'): | @@ -88,11 +104,15 @@ def init_brpy(br_loc='/usr/local/lib'): | ||
| 88 | br.br_img_channels.restype = c_int | 104 | br.br_img_channels.restype = c_int |
| 89 | br.br_img_is_empty.argtypes = [c_void_p] | 105 | br.br_img_is_empty.argtypes = [c_void_p] |
| 90 | br.br_img_is_empty.restype = c_bool | 106 | br.br_img_is_empty.restype = c_bool |
| 91 | - br.br_get_filename.argtypes = [c_void_p] | ||
| 92 | - br.br_get_filename.restype = c_char_p | 107 | + br.br_get_filename.argtypes = [c_char_p, c_int, c_void_p] |
| 108 | + br.br_get_filename.restype = c_int | ||
| 109 | + func4 = br.br_get_filename.__call__ | ||
| 110 | + br.br_get_filename = _handle_string_func(func4) | ||
| 93 | br.br_set_filename.argtypes = [c_void_p, c_char_p] | 111 | br.br_set_filename.argtypes = [c_void_p, c_char_p] |
| 94 | - br.br_get_metadata_string.argtypes = [c_void_p, c_char_p] | ||
| 95 | - br.br_get_metadata_string.restype = c_char_p | 112 | + br.br_get_metadata_string.argtypes = [c_char_p, c_int, c_void_p, c_char_p] |
| 113 | + br.br_get_metadata_string.restype = c_int | ||
| 114 | + func5 = br.br_get_metadata_string.__call__ | ||
| 115 | + br.br_get_metadata_string = _handle_string_func(func5) | ||
| 96 | br.br_enroll_template.argtypes = [c_void_p] | 116 | br.br_enroll_template.argtypes = [c_void_p] |
| 97 | br.br_enroll_template.restype = c_void_p | 117 | br.br_enroll_template.restype = c_void_p |
| 98 | br.br_enroll_template_list.argtypes = [c_void_p] | 118 | br.br_enroll_template_list.argtypes = [c_void_p] |