blob: 6cdc9b47d3babe96f2b49da1a7cb74aa458a4725 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <geode/CacheableKey.hpp>
#include <geode/CacheableString.hpp>
#include <geode/DataInput.hpp>
#include <geode/DataOutput.hpp>
#include <geode/ExceptionTypes.hpp>
#include <geode/Properties.hpp>
namespace apache {
namespace geode {
namespace client {
class PropertiesFile {
Properties& m_props;
std::string m_fileName;
public:
explicit PropertiesFile(Properties& props);
void parseLine(const std::string& line);
void readFile(const std::string& fileName);
char* nextBufferLine(char** cursor, char* bufbegin, size_t totalLen);
};
std::shared_ptr<Properties> Properties::create() {
return std::make_shared<Properties>();
}
std::shared_ptr<CacheableString> Properties::find(const std::string& key) {
return std::dynamic_pointer_cast<CacheableString>(
this->find(CacheableString::create(key)));
}
std::shared_ptr<Cacheable> Properties::find(
const std::shared_ptr<CacheableKey>& key) {
if (!key) {
throw NullPointerException("Properties::find: Null key given.");
}
auto entry = m_map.find(key);
if (entry != m_map.end()) {
return entry->second;
}
return nullptr;
}
void Properties::insert(std::string key, std::string value) {
this->insert(CacheableString::create(std::move(key)),
CacheableString::create(std::move(value)));
}
void Properties::insert(std::string key, const int value) {
this->insert(CacheableString::create(std::move(key)),
CacheableString::create(std::to_string(value)));
}
void Properties::insert(const std::shared_ptr<CacheableKey>& key,
const std::shared_ptr<Cacheable>& value) {
if (!key) {
throw NullPointerException("Properties::insert: Null key given.");
}
m_map[key] = value;
}
void Properties::remove(const std::string& key) {
this->remove(CacheableString::create(key));
}
void Properties::remove(const std::shared_ptr<CacheableKey>& key) {
m_map.erase(key);
}
size_t Properties::getSize() const { return m_map.size(); }
void Properties::foreach (Visitor& visitor) const {
for (auto& entry : m_map) {
visitor.visit(entry.first, entry.second);
}
}
void Properties::addAll(const std::shared_ptr<Properties>& other) {
if (other == nullptr) return;
for (auto& entry : other->m_map) {
m_map[entry.first] = entry.second;
}
}
void Properties::load(const std::string& fileName) {
PropertiesFile pf(*this);
pf.readFile(fileName);
}
PropertiesFile::PropertiesFile(Properties& props) : m_props(props) {}
void PropertiesFile::readFile(const std::string& fileName) {
char buf[8192];
FILE* fp = fopen(fileName.c_str(), "r");
if (fp != nullptr) {
size_t len = 0;
while ((len = fread(buf, 1, 8192, fp)) != 0) {
/* adongre
* CID 28894: String not null terminated (STRING_NULL)
* Function "fread" does not terminate string "*buf".
*/
buf[len] = '\0';
char* tmp = buf;
char* line = nullptr;
while ((line = nextBufferLine(&tmp, buf, len)) != nullptr) {
parseLine(line);
}
}
fclose(fp);
}
}
char* PropertiesFile::nextBufferLine(char** cursor, char* bufbegin,
size_t totalLen) {
if (static_cast<size_t>((*cursor) - bufbegin) >= totalLen) {
return nullptr;
}
char* lineBegin = *cursor;
while (((**cursor) != 10) && ((**cursor) != 13) &&
(static_cast<size_t>((*cursor) - bufbegin) < totalLen)) {
(*cursor)++;
}
**cursor = '\0';
(*cursor)++; // move to begin of next line.
return lineBegin;
}
void PropertiesFile::parseLine(const std::string& line) {
if (line.c_str()[0] == '#') {
return;
}
if (line.c_str()[0] == '/') {
return;
}
char key[1024];
char value[1024];
int res = sscanf(line.c_str(), "%[^ \t=]%*[ \t=]%[^\n\r]", key, value);
if (res != 2) {
// bad parse...
return;
}
// clean up value from trailing whitespace.
size_t len = strlen(value);
size_t end = len - 1;
while (end > 0) {
if (value[end] != ' ') {
break;
}
value[end] = '\0';
end--;
}
// clean up escape '\' sequences.
// size_t idx = 0;
// size_t widx = 0;
// len = strlen( value );
// while( idx < (len + 1 /* copy the Null terminator also */ ) ) {
// if ( value[idx] == '\\' ) {
// idx++;
// }
// value[widx] = value[idx];
// widx++;
// idx++;
//}
m_props.insert(key, value);
}
std::shared_ptr<Serializable> Properties::createDeserializable() {
return std::make_shared<Properties>();
}
DSCode Properties::getDsCode() const { return DSCode::Properties; }
void Properties::toData(DataOutput& output) const {
output.writeArrayLen(static_cast<uint32_t>(m_map.size()));
for (auto& entry : m_map) {
output.writeObject(entry.first);
output.writeObject(entry.second);
}
}
void Properties::fromData(DataInput& input) {
auto mapSize = input.readArrayLength();
m_map.reserve(mapSize);
for (int i = 0; i < mapSize; i++) {
auto key = std::dynamic_pointer_cast<CacheableKey>(input.readObject());
auto value = std::dynamic_pointer_cast<Cacheable>(input.readObject());
m_map.emplace(key, value);
}
}
} // namespace client
} // namespace geode
} // namespace apache