Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ cmake-build*
*.swp

.cache

src/version.hpp
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ set(libcimpp_MINOR_VERSION 2)
set(libcimpp_PATCH_VERSION 0)
set(libcimpp_VERSION ${libcimpp_MAJOR_VERSION}.${libcimpp_MINOR_VERSION}.${libcimpp_PATCH_VERSION})

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/version.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/version.hpp)

# Options
option(BUILD_SHARED_LIBS "Build shared library" OFF)
option(CIMPP_BUILD_EXAMPLES "Build examples" OFF)
Expand Down
120 changes: 109 additions & 11 deletions examples/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
#include <iostream>
#include <string>
#include "CIMModel.hpp"
#include "CimConstants.hpp"
#include "BaseClass.hpp"
#include "IdentifiedObject.hpp"
#include "version.hpp"

std::string formatName(std::string name) {
if (name.length() > 12) {
name.resize(10, ' ');
name += ".. ";
}
else {
name.resize(14, ' ');
}
return name;
}
// forward declerations
static std::string format_name(std::string name);
static std::size_t utf8_code_point_len(const std::string& txt);
static std::size_t utf8_code_point_len(const char* ptr);
static void utf8_code_point_resize(std::string& txt, std::size_t new_len, char fill);

int main(int argc, char** argv)
{
if(argc < 2)
{
std::cout << "Usage: example <cim file> [additional cim files]" << std::endl;
std::cout << "Provide at least one cim file" << std::endl;
std::cout << "Version: libcimpp " << RELEASE_VERSION << " (" << CimVersion << ")" << std::endl;
return 1;
}

Expand Down Expand Up @@ -52,7 +50,7 @@ int main(int argc, char** argv)
if (IdObj->name.initialized)
{
static unsigned int i = 0;
std::string outputName = formatName(IdObj->name);
std::string outputName = format_name(IdObj->name);
std::cout << outputName;
i++;
if (i % 5 == 0) {
Expand All @@ -64,3 +62,103 @@ int main(int argc, char** argv)
std::cout << std::endl;
return 0;
}

static std::string format_name(std::string name)
{
if (utf8_code_point_len(name) > 12)
{
utf8_code_point_resize(name, 10, ' ');
name += ".. ";
}
else
{
utf8_code_point_resize(name, 14, ' ');
}
return name;
}

static std::size_t utf8_code_point_len(const std::string& txt)
{
return utf8_code_point_len(txt.c_str());
}

static std::size_t utf8_code_point_len(const char* ptr)
{
size_t len = 0;
for (; *ptr != 0; ++ptr)
{
if ((*ptr & 0b11000000) != 0b10000000)
{
++len;
}
}
return len;
}

static void utf8_code_point_resize(std::string& txt, std::size_t new_len, char fill)
{
const char* ptr = txt.c_str();
size_t len = 0;
for (; *ptr != 0 && len <= new_len; ++ptr)
{
if ((*ptr & 0b11000000) != 0b10000000)
{
++len;
}
}
if (len <= new_len)
{
new_len += txt.length() - len;
}
else
{
new_len = ptr - 1 - txt.c_str();
}
txt.resize(new_len, fill);
}

static bool utf8_check_valid(const char* ptr, std::size_t* p_len = nullptr)
{
bool valid = true;
size_t len = 0;
for (; *ptr != 0; ++ptr)
{
if ((*ptr & 0b11000000) != 0b10000000)
{
++len;
size_t inner_code_point_len = 0;
if ((*ptr & 0b11100000) == 0b11000000) // 110xxxxx
{
inner_code_point_len = 1;
}
if ((*ptr & 0b11110000) == 0b11100000) // 1110xxxx
{
inner_code_point_len = 2;
}
if ((*ptr & 0b11111000) == 0b11110000) // 11110xxx
{
inner_code_point_len = 3;
}
for (size_t idx = 0; idx < inner_code_point_len; ++idx, ++ptr)
{
if ((*ptr & 0b11000000) != 0b10000000)
{
valid = false;
}
if (*ptr == 0)
{
break;
}
}
}
else
{
valid = false;
}
}
if (p_len != nullptr)
{
*p_len = len;
}
return valid;
}
3 changes: 3 additions & 0 deletions examples/src/readwrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@

#include "CIMModel.hpp"
#include "CIMWriter.hpp"
#include "CimConstants.hpp"
#include "version.hpp"

int main(int argc, char** argv)
{
if (argc < 3)
{
std::cout << "Usage: readwrite <cim file> [additional cim files] <outputfile>" << std::endl;
std::cout << "Provide at least one cim file and outputfile" << std::endl;
std::cout << "Version: libcimpp " << RELEASE_VERSION << " (" << CimVersion << ")" << std::endl;
return 1;
}
std::string outputfile = argv[argc-1];
Expand Down
32 changes: 9 additions & 23 deletions src/CIMContentHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ void CIMContentHandler::startElement(const std::string &namespaceURI, const std:

// Remember last opened tag
tagStack.push(qName);
value.clear();

// If there is no RDF ID (an XML attribute!) then we don't have a new CIM
// object or RDF relation therefore the XML element will contain a value
Expand Down Expand Up @@ -148,11 +149,16 @@ void CIMContentHandler::startElement(const std::string &namespaceURI, const std:
void CIMContentHandler::endElement(const std::string &namespaceURI, const std::string &localName, const std::string &qName)
{
// Only process tags in cim namespace
if(qName.find("cim:") == std::string::npos)
if (qName.find("cim:") == std::string::npos)
{
return;
}

if (!tagStack.empty() && !objectStack.empty() && !value.empty())
{
assign(objectStack.top(), tagStack.top(), value);
}

// Pop Stacks
if (tagStack.size() == 0) {
std::cerr << "WARNING: Nearly tried to pop empty tag stack for tag: " << qName << std::endl;
Expand All @@ -174,27 +180,7 @@ void CIMContentHandler::endElement(const std::string &namespaceURI, const std::s

void CIMContentHandler::characters(const std::string &characters)
{
// Only process tags in "cim" namespace
if(tagStack.empty())
{
return;
}
if(objectStack.empty())
{
throw CriticalError("CIMContentHandler: Critical Error: objectStack empty");
}

#ifndef DEBUG
assign(objectStack.top(), tagStack.top(), characters);
#else
// Check if the characters only contain whitespace
if(is_only_whitespace(characters))
{
return;
}
if(!assign(objectStack.top(), tagStack.top(), characters))
std::cout << "CIMContentHandler: Note: Cannot assign '" << characters << "' to " << tagStack.top() << std::endl;
#endif
value.append(characters);
}

void CIMContentHandler::ignorableWhitespace(const std::string &ch)
Expand Down Expand Up @@ -244,7 +230,7 @@ std::string CIMContentHandler::get_rdf_enum(const AttributesT &attributes)
{
if(attributes.getQName(i) == "rdf:resource")
{
std::regex expr("^http[s]*://[a-zA-Z0-9./_]*CIM-schema-cim[0-9]+#([a-zA-z0-9]*).([a-zA-z0-9]*)");
std::regex expr("^http[s]*://.*#([a-zA-z0-9]*).([a-zA-z0-9]*)");
std::smatch m;
std::string str = attributes.getValue(i);
if(std::regex_match(str, m, expr))
Expand Down
1 change: 1 addition & 0 deletions src/CIMContentHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class CIMContentHandler : public Arabica::SAX::ContentHandler<std::string>
std::stack<BaseClass*> objectStack;
std::stack<std::string> tagStack;
std::list<Task> taskQueue;
std::string value;
};


Expand Down
25 changes: 24 additions & 1 deletion src/CIMWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ bool CIMWriter::writeCim(std::ostream& rdf, const std::vector<BaseClass*>& objLi
std::stringstream stream;
if (func(obj, stream))
{
rdfObj << " <" << attr << ">" << stream.str() << "</" << attr << ">" << std::endl;
rdfObj << " <" << attr << ">" << xmlEscape(stream.str()) << "</" << attr << ">" << std::endl;
++attributesCount;
}
}
Expand Down Expand Up @@ -232,3 +232,26 @@ CGMESProfile CIMWriter::getAttributeProfile(const BaseClass* obj, const std::str
}
return UnknownProfile;
}

std::string CIMWriter::xmlEscape(const std::string& txt)
{
if (txt.find_first_of("&<>'\"") == std::string::npos)
{
return txt;
}
std::string result;
result.reserve(txt.size() + 10);
for (size_t pos = 0; pos != txt.size(); ++pos)
{
switch (txt[pos])
{
case '&': result.append("&amp;"); break;
case '<': result.append("&lt;"); break;
case '>': result.append("&gt;"); break;
case '\'': result.append("&apos;"); break;
case '"': result.append("&quot;"); break;
default: result.append(&txt[pos], 1); break;
}
}
return result;
}
3 changes: 3 additions & 0 deletions src/CIMWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ class CIMWriter
*/
static CGMESProfile getAttributeProfile(const BaseClass* obj, const std::string& attr,
const CGMESProfile& classProfile);

private:
static std::string xmlEscape(const std::string& txt);
};

#endif // CIMWRITER_HPP
1 change: 1 addition & 0 deletions src/version.hpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define RELEASE_VERSION "${libcimpp_VERSION}"