I just read Joel's blog post on unicode, and found the characters the I want to use to draw boxes in the console in this pdf from the unicode website.
Displaying these characters is simple enough when done directly with cout, i.e. the following does what it is supposed to do..
cout << u8"\u256C";
However, I am doing some overloading as shown in the following snippets, and I cannot figure out how to get the box characters to display correctly.
I render my data like so ...
// This is the main rendering code
ostream& operator<<(ostream& os, const DataGrid& dg)
{
for(auto row : dg.data)
{
string tmp; //Make empty string
for(auto col : row)
tmp.append( 1, dg.gfxString[col] );
os << tmp << endl;
}
return os;
}
Make it friends with my data model...
class DataGrid
{
public:
friend ostream& operator<<(ostream& os, const DataGrid& dg);
//EDIT: rest of class added on request
DataGrid(Rectangle _rect = Rectangle(Point(0,0), Point(5,5))) :
rect(_rect),
data ( vector<vector<p_t>> (_rect.getHeight(), vector<p_t>(_rect.getWidth(), p_t::EMPTY)) ){}
void addPoint(Point p, p_t type)
{
data[p.getY()][p.getX()] = type;
}
void addBorder()
{
//Top and bottom
fill_n(data[0].begin()+1, rect.getWidth()-2, p_t::BORDER_T);
fill_n(data[rect.getBtm()].begin()+1, rect.getWidth()-2, p_t::BORDER_B);
//Left and right hand border edges
for (int nn=1; nn<rect.getHeight()-1; ++nn){
addPoint(Point(rect.getLeft(), nn), p_t::BORDER_L);
addPoint(Point(rect.getRight(), nn), p_t::BORDER_R);
}
//Corners
addPoint(rect.getTL(), p_t::BORDER_TL);
addPoint(rect.getTR(), p_t::BORDER_TR);
addPoint(rect.getBL(), p_t::BORDER_BL);
addPoint(rect.getBR(), p_t::BORDER_BR);
}
private:
Rectangle rect;
vector<vector<p_t>> data; //p_t is an enum
//string gfxString = " abcdefghijklmnop"; //This works fine
string gfxString = u8"\u256C\u256C\u256C\u256C\u256C\u256C\u256C\u256C"; //Nope
};
Then attempt to render it with the following, but get gibberish ...
DataGrid p = DataGrid(Rectangle(Point(0,0), 40, 10));
p.addBorder();
cout << p;
If anyone can spot a fix, then that would be great. Thanks for reading.
I'd change gfxString to a vector of std::strings (or even a std::array):
// Probably in the final code, these are not all the same value
std::array<std::string, 8> gfxString = {
{ u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
}};
Or even just an array of const char*.
Related
In some testing code there's a helper function like this:
auto make_condiment(bool salt, bool pepper, bool oil, bool garlic) {
// assumes that first bool is salt, second is pepper,
// and so on...
//
// Make up something according to flags
return something;
};
which essentially builds up something based on some boolean flags.
What concerns me is that the meaning of each bool is hardcoded in the name of the parameters, which is bad because at the call site it's hard to remember which parameter means what (yeah, the IDE can likely eliminate the problem entirely by showing those names when tab completing, but still...):
// at the call site:
auto obj = make_condiment(false, false, true, true); // what ingredients am I using and what not?
Therefore, I'd like to pass a single object describing the settings. Furthermore, just aggregating them in an object, e.g. std::array<bool,4>.
I would like, instead, to enable a syntax like this:
auto obj = make_smart_condiment(oil + garlic);
which would generate the same obj as the previous call to make_condiment.
This new function would be:
auto make_smart_condiment(Ingredients ingredients) {
// retrieve the individual flags from the input
bool salt = ingredients.hasSalt();
bool pepper = ingredients.hasPepper();
bool oil = ingredients.hasOil();
bool garlic = ingredients.hasGarlic();
// same body as make_condiment, or simply:
return make_condiment(salt, pepper, oil, garlic);
}
Here's my attempt:
struct Ingredients {
public:
enum class INGREDIENTS { Salt = 1, Pepper = 2, Oil = 4, Garlic = 8 };
explicit Ingredients() : flags{0} {};
explicit Ingredients(INGREDIENTS const& f) : flags{static_cast<int>(f)} {};
private:
explicit Ingredients(int fs) : flags{fs} {}
int flags; // values 0-15
public:
bool hasSalt() const {
return flags % 2;
}
bool hasPepper() const {
return (flags / 2) % 2;
}
bool hasOil() const {
return (flags / 4) % 2;
}
bool hasGarlic() const {
return (flags / 8) % 2;
}
Ingredients operator+(Ingredients const& f) {
return Ingredients(flags + f.flags);
}
}
salt{Ingredients::INGREDIENTS::Salt},
pepper{Ingredients::INGREDIENTS::Pepper},
oil{Ingredients::INGREDIENTS::Oil},
garlic{Ingredients::INGREDIENTS::Garlic};
However, I have the feeling that I am reinventing the wheel.
Is there any better, or standard, way of accomplishing the above?
Is there maybe a design pattern that I could/should use?
I think you can remove some of the boilerplate by using a std::bitset. Here is what I came up with:
#include <bitset>
#include <cstdint>
#include <iostream>
class Ingredients {
public:
enum Option : uint8_t {
Salt = 0,
Pepper = 1,
Oil = 2,
Max = 3
};
bool has(Option o) const { return value_[o]; }
Ingredients(std::initializer_list<Option> opts) {
for (const Option& opt : opts)
value_.set(opt);
}
private:
std::bitset<Max> value_ {0};
};
int main() {
Ingredients ingredients{Ingredients::Salt, Ingredients::Pepper};
// prints "10"
std::cout << ingredients.has(Ingredients::Salt)
<< ingredients.has(Ingredients::Oil) << "\n";
}
You don't get the + type syntax, but it's pretty close. It's unfortunate that you have to keep an Option::Max, but not too bad. Also I decided to not use an enum class so that it can be accessed as Ingredients::Salt and implicitly converted to an int. You could explicitly access and cast if you wanted to use enum class.
If you want to use enum as flags, the usual way is merge them with operator | and check them with operator &
#include <iostream>
enum Ingredients{ Salt = 1, Pepper = 2, Oil = 4, Garlic = 8 };
// If you want to use operator +
Ingredients operator + (Ingredients a,Ingredients b) {
return Ingredients(a | b);
}
int main()
{
using std::cout;
cout << bool( Salt & Ingredients::Salt ); // has salt
cout << bool( Salt & Ingredients::Pepper ); // doesn't has pepper
auto sp = Ingredients::Salt + Ingredients::Pepper;
cout << bool( sp & Ingredients::Salt ); // has salt
cout << bool( sp & Ingredients::Garlic ); // doesn't has garlic
}
note: the current code (with only the operator +) would not work if you mix | and + like (Salt|Salt)+Salt.
You can also use enum class, just need to define the operators
I would look at a strong typing library like:
https://github.com/joboccara/NamedType
For a really good video talking about this:
https://www.youtube.com/watch?v=fWcnp7Bulc8
When I first saw this, I was a little dismissive, but because the advice came from people I respected, I gave it a chance. The video convinced me.
If you look at CPP Best Practices and dig deeply enough, you'll see the general advice to avoid boolean parameters, especially strings of them. And Jonathan Boccara gives good reasons why your code will be stronger if you don't directly use the raw types, for the very reason that you've already identified.
In order to read all shapes within my step file, I have succeed to extract all shapes using STEPControl_reader.
Now I want to find a way (OCAF/XDE ?) to extract a tree view containing which shape is contained by another one.
Could anyone give some pointers to examples extracting those informations in step file using OCAF or XDE.
I have a difficulty to understand the official document because it has a lack of examples.
EDIT:
By using the Mayo project:
You can use the XdeDocumentItem::XdeDocumentItem(...) constructor and recursively creating the nodes.
XdeDocumentItem::XdeDocumentItem(const Handle_TDocStd_Document &doc)
: m_cafDoc(doc),
m_shapeTool(XCAFDoc_DocumentTool::ShapeTool(doc->Main())),
m_colorTool(XCAFDoc_DocumentTool::ColorTool(doc->Main())){
this->rebuildAssemblyTree();}
The method rebuildAssemblyTree is like that:
for (const TDF_Label& rootLabel : this->topLevelFreeShapes())
this->deepBuildAssemblyTree(0, rootLabel);
You may use class XCAFPrs_DocumentExplorer for stack-alike traverse within OCCT 7.4.0+, and the following code snippet (based on XDisplay Draw Harness command) for traverse with recursive function calls:
//! Handle document root shapes.
int traverseDocument (const Handle(TDocStd_Document)& theDoc)
{
TDF_LabelSequence aLabels;
XCAFDoc_DocumentTool::ShapeTool (theDoc->Main())->GetFreeShapes (aLabels);
for (TDF_LabelSequence::Iterator aLabIter (myLabels); aLabIter.More(); aLabIter.Next())
{
const TDF_Label& aLabel = aLabIter.Value();
if (traverseLabel (aLabel, "", TopLoc_Location()) == 1)
{
return 1;
}
}
return 0;
}
//! Handle single label.
int traverseLabel (const TDF_Label& theLabel,
const TCollection_AsciiString& theNamePrefix,
const TopLoc_Location& theLoc)
{
TCollection_AsciiString aName;
{
Handle(TDataStd_Name) aNodeName;
if (theLabel.FindAttribute (TDataStd_Name::GetID(), aNodeName))
{
aName = aNodeName->Get(); // instance name
}
if (aName.IsEmpty())
{
TDF_Label aRefLabel;
if (XCAFDoc_ShapeTool::GetReferredShape (theLabel, aRefLabel)
&& aRefLabel.FindAttribute (TDataStd_Name::GetID(), aNodeName))
{
aName = aNodeName->Get(); // product name
}
}
}
aName = theNamePrefix + aName;
TDF_Label aRefLabel = theLabel;
XCAFDoc_ShapeTool::GetReferredShape (theLabel, aRefLabel);
if (XCAFDoc_ShapeTool::IsAssembly (aRefLabel))
{
aName += "/";
const TopLoc_Location aLoc = theLoc * XCAFDoc_ShapeTool::GetLocation (theLabel);
for (TDF_ChildIterator aChildIter (aRefLabel); aChildIter.More(); aChildIter.Next())
{
if (traverseLabel (aChildIter.Value(), aName, aLoc) == 1)
{
return 1;
}
}
return 0;
}
std::cout << aName << " ";
return 0;
}
I want to rewrite all messages in my code,
I need replace only selectors, but I need be able to replace nested expressions
f. e. :
[super foo:[someInstance someMessage:#""] foo2:[someInstance someMessage2]];
I tried do it with clang::Rewriter replaceText and just generate new string,
but there is a problem: It would not be work if I change selectors length, because I replace nested messages with those old positions.
So, I assumed that I need to use clang::Rewriter ReplaceStmt(originalStatement, newStatement);
I am using RecursiveASTVisitor to visit all messages, and I want to copy those messages objects, and replace selectors:
How can I do that?
I tried use ObjCMessageExpr::Create but there is so meny args, I don't know how to get ASTContext &Context and ArrayRef<SourceLocation> SeLocs and Expr *Receiver parameters from the original message.
What is the proper way to replace selectors in nested messages using clang tool (clang tooling interface)?
Update:
Should I use ReplaceStmtWithStmt callback and ASTMatchFinder ?
Update:
I am using following function to rewrite text in file:
void ReplaceText(SourceLocation start, unsigned originalLength, StringRef string) {
m_rewriter.ReplaceText(start, originalLength, string);
m_rewriter.overwriteChangedFiles();
}
And I want to replace all messageExpr in code with new selector f.e:
how it was:
[object someMessage:[object2 someMessage:obj3 calculate:obj4]];
how it should be:
[object newSelector:[object2 newSelector:obj3 newSelector:obj4]];
I am using ReqoursiveASTVisitor:
bool VisitStmt(Stmt *statement) {
if (ObjCMessageExpr *messageExpr = dyn_cast<ObjCMessageExpr>(statement)) {
ReplaceMessage(*messageExpr)
}
return true;
}
I created method for generating new message expr string:
string StringFromObjCMessageExpr(ObjCMessageExpr& messageExpression) {
std::ostringstream stringStream;
const string selectorString = messageExpression.getSelector().getAsString();
cout << selectorString << endl;
vector<string> methodParts;
split(selectorString, ParametersDelimiter, methodParts);
stringStream << "[" ;
const string receiver = GetStringFromLocations(m_compiler, messageExpression.getReceiverRange().getBegin(), messageExpression.getSelectorStartLoc());
stringStream << receiver;
clang::ObjCMessageExpr::arg_iterator argIterator = messageExpression.arg_begin();
for (vector<string>::const_iterator partsIterator = methodParts.begin();
partsIterator != methodParts.end();
++partsIterator) {
stringStream << "newSelector";
if (messageExpression.getNumArgs() != 0) {
const clang::Stmt *argument = *argIterator;
stringStream << ":" << GetStatementString(*argument) << " ";
++argIterator;
}
}
stringStream << "]";
return stringStream.str();
}
void ReplaceMessage(ObjCMessageExpr& messageExpression) {
SourceLocation locStart = messageExpression.getLocStart();
SourceLocation locEnd = messageExpression.getLocEnd();
string newExpr = StringFromObjCMessageExpr(messageExpression);
const int exprStringLegth = m_rewriter.getRangeSize(SourceRange(locStart, locEnd));
ReplaceText(locStart, exprStringLegth, newExpr);
}
The problem occurs when I try to replace nested messages, like that:
[simpleClass doSomeActionWithString:string3 andAnotherString:string4];
[simpleClass doSomeActionWithString:str andAnotherString:str2];
[simpleClass doSomeActionWithString:#"" andAnotherString:#"asdasdsad"];
[simpleClass setSimpleClassZAZAZAZAZAZAZAZA:[simpleClass getSimpleClassZAZAZAZAZAZAZAZA]];
the result is:
[simpleClass newSelector:string3 newSelector:string4 ];
[simpleClass newSelector:str newSelector:str2 ];
[simpleClass newSelector:#"" newSelector:#"asdasdsad" ];
[simpleClass newSelector:[simpleClass getSimp[simpleClass newSelector]];
because messageExpression has "old" value of getLocStart(); and getLocEnd(); How can I fix it?
You can rewrite selector name by replacing only continuous parts of selector name. For example, replace only underlined parts
[object someMessage:[object2 someMessage:obj3 calculate:obj4]];
^~~~~~~~~~~ ^~~~~~~~~~~ ^~~~~~~~~
To achieve this you require only
number of selector parts - ObjCMessageExpr::getNumSelectorLocs()
their locations - ObjCMessageExpr::getSelectorLoc(index)
their lengths - ObjCMessageExpr::getSelector().getNameForSlot(index).size().
Overall, you can rewrite ObjCMessageExpr with the following RecursiveASTVisitor:
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Rewrite/Core/Rewriter.h"
namespace clang_tooling
{
using clang::SourceLocation;
class RewritingVisitor : public clang::ASTConsumer,
public clang::RecursiveASTVisitor<RewritingVisitor>
{
public:
// You can obtain SourceManager and LangOptions from CompilerInstance when
// you are creating visitor (which is also ASTConsumer) in
// clang::ASTFrontendAction::CreateASTConsumer.
RewritingVisitor(clang::SourceManager &sourceManager,
const clang::LangOptions &langOptions)
: _sourceManager(sourceManager), _rewriter(sourceManager, langOptions)
{}
virtual void HandleTranslationUnit(clang::ASTContext &context)
{
TraverseDecl(context.getTranslationUnitDecl());
_rewriter.overwriteChangedFiles();
}
bool VisitObjCMessageExpr(clang::ObjCMessageExpr *messageExpr)
{
if (_sourceManager.isInMainFile(messageExpr->getLocStart()))
{
clang::Selector selector = messageExpr->getSelector();
for (unsigned i = 0, end = messageExpr->getNumSelectorLocs();
i < end; ++i)
{
SourceLocation selectorLoc = messageExpr->getSelectorLoc(i);
_rewriter.ReplaceText(selectorLoc,
selector.getNameForSlot(i).size(),
"newSelector");
}
}
return Base::VisitObjCMessageExpr(messageExpr);
}
private:
typedef clang::RecursiveASTVisitor<RewritingVisitor> Base;
clang::SourceManager &_sourceManager;
clang::Rewriter _rewriter;
};
} // end namespace clang_tooling
I am using Qt Creator to develop an application.
I am not a good C++ programmer, so there might be conceptual errors etc.
I am facing an issue while copying the array of structure and return the structure.
There are ample of solutions related to similar title but could'nt solved my problem.
Here's my code:
ABC.h
typedef struct command_packet_struct
{
QString ItemDataName;
DATA_TYPE ItemDataType;
int ItemDataLength;
} COMMAND_PACKET_STRUCT;
class ABC
{
private:
COMMAND_PACKET_STRUCT* getHeaderTitle(int index);
COMMAND_PACKET_STRUCT *_packetStruct ;
};
ABC.cpp
COMMAND_PACKET_STRUCT _OA_Packet [] = {
{"ERROR\nMAIN CODE" , DATA_TYPE_NUM, 5 },
{"ERROR\nSUB CODE" , DATA_TYPE_NUM, 4 },
{"SCALE VERSION" , DATA_TYPE_ASCII, 8 },
{"E-PRE VERSION" , DATA_TYPE_ASCII, 8 }
};
COMMAND_PACKET_STRUCT* PCU_SIM_ORDER_TASK::getHeaderTitle(int index)
{
int maxSize;
if (_packetStruct != NULL)
{
_packetStruct = 0;
}
_packetStruct = new COMMAND_PACKET_STRUCT(*_OA_Packet);
maxSize = ((sizeof(_OA_Packet)/sizeof(COMMAND_PACKET_STRUCT)) - 1);
memcpy(_packetStruct, _OA_Packet, maxSize) ;
qDebug() << sizeof(COMMAND_PACKET_STRUCT); // return 12
qDebug() << sizeof(_packetStruct); // return 4
qDebug() << sizeof(_OA_Packet); // return 48
return _packetStruct;
}
The above code shows the implementation i have done for Array of structures.
I need to copy array of structure
_OA_Packet
to
_packetStruct
but when I try to get the size of the _packetStruct, it gives 4 while the size of _OA_Packet gives 48
Thus when try to display the contents of the structure, it returns with "segmentation fault error"
Any Idea, Suggestion ??
Your struct COMMAND_PACKET_STRUCT should be defined like this in C++
struct COMMAND_PACKET_STRUCT
{
QString ItemDataName;
DATA_TYPE ItemDataType;
int ItemDataLength;
};
use your default constructor to allocate space.
maxSize = ((sizeof(_OA_Packet)/sizeof(COMMAND_PACKET_STRUCT)));
_packetStruct = new COMMAND_PACKET_STRUCT[maxSize];
Copy content.
std::copy(_OA_Packet,_OA_Packet+maxSize,_packetStruct);
_packetStruct is pointer, you probably want to check the data size it points to.
qDebug() << sizeof(*_packetStruct); // return 4 -->will be 12
I am trying to use a rich edit control to output some text on the screen:
Monday Press 1.
Your day is Monday
Tuesday Press 2.
I can't really find any simple examples of how to do this. all i have been able to sort out is setting the window text (setWindowText), but everything else is escaping me.
Any short examples?
Despite the comments, I'm going to answer the question you asked, about how to format data in a Rich Edit control. A few years ago, I had to do this, and came up with something that I could treat a little like an IOstream (if I were doing it today, I'd probably do it a bit differently, but such is life).
First, code to act like an IOstream, but write to a rich-edit control:
// rich_stream.h:
#ifndef RICH_STREAM_H
#define RICH_STREAM_H
class rich_stream {
CRichEditCtrl &ctrl;
public:
rich_stream(CRichEditCtrl &ctrl_) : ctrl(ctrl_) { }
void add_text(char const *txt) {
ctrl.SetSel(-1,-1);
ctrl.ReplaceSel(txt);
}
void add_int(int val) {
CString temp;
temp.Format("%d", val);
add_text(temp);
}
void set_char_format(CHARFORMAT &fmt) {
ctrl.SetSelectionCharFormat(fmt);
}
};
inline rich_stream &operator<<(rich_stream &s, char const *t) {
s.add_text(t);
return s;
}
inline rich_stream &operator<<(rich_stream &s, CHARFORMAT &fmt) {
s.set_char_format(fmt);
return s;
}
inline CString nl() {
return CString("\n\n");
}
inline rich_stream &operator<<(rich_stream &s, CString (*f)()) {
s.add_text(f());
return s;
}
inline rich_stream &operator<<(rich_stream &s, int val) {
s.add_int(val);
return s;
}
#endif
Then, I'd use this something like:
CHARFORMAT bold;
memset(&bold, 0, sizeof(bold));
bold.cbSize = sizeof(bold);
bold.dwMask = CFM_BOLD | CFM_FACE | CFM_SIZE;
bold.dwEffects = CFE_BOLD;
strcpy(bold.szFaceName, "Times");
bold.yHeight = 14 * 20;
CHARFORMAT normal;
memset(&normal, 0, sizeof(normal));
normal.cbSize = sizeof(normal);
normal.dwMask = CFM_BOLD | CFM_FACE | CFM_SIZE;
normal.dwEffects = 0;
strcpy(normal.szFaceName, "Times");
normal.yHeight = 14 * 20;
// ...
rich_stream txt(GetRichEditCtrl());
txt << bold << "Heading 1: " << normal << info1 << nl
<< bold << "Heading 2: " << normal << info2 << nl
<< bold << "Heading 3: " << normal << info3;
If I were doing this today, I'd almost certainly create a small class as a wrapper for a CHARFORMAT so I could construct the formatting objects a little more cleanly. I'd probably also at least think hard about implementing it as a normal iostream with a stream buffer that inserted data into the rich edit control (but at the time I didn't know streams well enough to know I should do that).
Glancing at it, there are a few other things that aren't really exactly right either -- add_text uses SetSel(-1, -1);. This should really retrieve the current length of the text (e.g., with GetWindowTextLength, and set the selection to just after the end.
Use Wordpad, it's an RichEdit control too. It will generate your RTF in a way that's naturally compatible with your control.