camenduru's picture
ceres-solver and colmap
7b7496d
// Copyright (c) 2022, ETH Zurich and UNC Chapel Hill.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
#include "util/string.h"
#include <algorithm>
#include <cstdarg>
#include <fstream>
#include <sstream>
#include <boost/algorithm/string.hpp>
namespace colmap {
namespace {
// The StringAppendV function is borrowed from Google under the BSD license:
//
// Copyright 2012 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
void StringAppendV(std::string* dst, const char* format, va_list ap) {
// First try with a small fixed size buffer.
static const int kFixedBufferSize = 1024;
char fixed_buffer[kFixedBufferSize];
// It is possible for methods that use a va_list to invalidate
// the data in it upon use. The fix is to make a copy
// of the structure before using it and use that copy instead.
va_list backup_ap;
va_copy(backup_ap, ap);
int result = vsnprintf(fixed_buffer, kFixedBufferSize, format, backup_ap);
va_end(backup_ap);
if (result < kFixedBufferSize) {
if (result >= 0) {
// Normal case - everything fits.
dst->append(fixed_buffer, result);
return;
}
#ifdef _MSC_VER
// Error or MSVC running out of space. MSVC 8.0 and higher
// can be asked about space needed with the special idiom below:
va_copy(backup_ap, ap);
result = vsnprintf(nullptr, 0, format, backup_ap);
va_end(backup_ap);
#endif
if (result < 0) {
// Just an error.
return;
}
}
// Increase the buffer size to the size requested by vsnprintf,
// plus one for the closing \0.
const int variable_buffer_size = result + 1;
std::unique_ptr<char[]> variable_buffer(new char[variable_buffer_size]);
// Restore the va_list before we use it again.
va_copy(backup_ap, ap);
result =
vsnprintf(variable_buffer.get(), variable_buffer_size, format, backup_ap);
va_end(backup_ap);
if (result >= 0 && result < variable_buffer_size) {
dst->append(variable_buffer.get(), result);
}
}
bool IsNotWhiteSpace(const int character) {
return character != ' ' && character != '\n' && character != '\r' &&
character != '\t';
}
} // namespace
std::string StringPrintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
std::string result;
StringAppendV(&result, format, ap);
va_end(ap);
return result;
}
std::string StringReplace(const std::string& str, const std::string& old_str,
const std::string& new_str) {
if (old_str.empty()) {
return str;
}
size_t position = 0;
std::string mod_str = str;
while ((position = mod_str.find(old_str, position)) != std::string::npos) {
mod_str.replace(position, old_str.size(), new_str);
position += new_str.size();
}
return mod_str;
}
std::string StringGetAfter(const std::string& str, const std::string& key) {
if (key.empty()) {
return str;
}
std::size_t found = str.rfind(key);
if (found != std::string::npos) {
return str.substr(found + key.length(),
str.length() - (found + key.length()));
}
return "";
}
std::vector<std::string> StringSplit(const std::string& str,
const std::string& delim) {
std::vector<std::string> elems;
boost::split(elems, str, boost::is_any_of(delim), boost::token_compress_on);
return elems;
}
bool StringStartsWith(const std::string& str, const std::string& prefix) {
return !prefix.empty() && prefix.size() <= str.size() &&
str.substr(0, prefix.size()) == prefix;
}
void StringLeftTrim(std::string* str) {
str->erase(str->begin(),
std::find_if(str->begin(), str->end(), IsNotWhiteSpace));
}
void StringRightTrim(std::string* str) {
str->erase(std::find_if(str->rbegin(), str->rend(), IsNotWhiteSpace).base(),
str->end());
}
void StringTrim(std::string* str) {
StringLeftTrim(str);
StringRightTrim(str);
}
void StringToLower(std::string* str) {
std::transform(str->begin(), str->end(), str->begin(), ::tolower);
}
void StringToUpper(std::string* str) {
std::transform(str->begin(), str->end(), str->begin(), ::toupper);
}
bool StringContains(const std::string& str, const std::string& sub_str) {
return str.find(sub_str) != std::string::npos;
}
} // namespace colmap