QString parse system variables - c++

How I should parse QString, which contains system variables ?What I want:
QString path = "%WINDIR%\\System32\\";
QString output = parse(path);
QDebug()<<output; \\ output is "C:\\Windows\\System32\\"

I think you want something like this:
// Untested
QString parse(QString str)
{
int pos = 0;
QRegExp rx("%([^%]+)%"); // Match env var between two '%'
rx.setMinimal(true);
while((pos = rx.indexIn(str, pos)) != -1)
{
// Replace env var
QString capture = rx.cap(1);
QString replacement = getenv(capture.toAscii());
str.replace("%" + capture + "%", replacement);
// Skip env var + two '%'
pos += rx.matchedLength() + 2;
}
return str;
}
QString path = parse("%WINDIR%\\System32");

I think, this is what you looking for. Please try this
QString windir = getenv ("WINDIR"); // Expanded
if (windir.isEmpty()) {
fprintf(stderr, "Generator requires WINDIRto be set\n");
}
windir += "\\System32";
qDebug()<<windir;

Related

MongoDB C driver: how to use regex query collection?

for example, In MySQL the query like this:
select name from test_tab where id = 1 and name like 'test%';
I want to translate this query in mongodb by mongodb C driver, so I write the code like this, but all don't work(the searchDoc() function is okay.
string strName = "";
bson_t *cond = bson_new();
BSON_APPEND_INT32(cond, "id", 1);
if (strlen(name.c_str()) > 0)
{
strName = "/^" + name + "/";
bson_t *child;
child = bson_new();
bson_append_document_begin(cond, "name", -1, child);
BSON_APPEND_UTF8(child, "$regex", strName.c_str());
bson_append_document_end(cond, child);
}
mongoc_cursor_t *cursor(NULL);
int iRet = searchDoc("db", "test_tab", cond, cursor);
if (iRet < 0)
{
bson_destroy(cond);
mongoc_cursor_destroy(cursor);
return -1;
}
and
string strName = "";
bson_t *cond = bson_new();
BSON_APPEND_INT32(cond, "id", 1);
if (strlen(name.c_str()) > 0)
{
strName = "/^" + name + ".*/";
BSON_APPEND_REGEX(cond, "name", strName.c_str(), "i");
}
mongoc_cursor_t *cursor(NULL);
int iRet = searchDoc("db", "test_tab", cond, cursor);
if (iRet < 0)
{
bson_destroy(cond);
mongoc_cursor_destroy(cursor);
return -1;
}
How can I build the regex pattern to query record work okay?
Thank you
I seach this page: https://jira.mongodb.org/browse/CDRIVER-206,
there is a important tips: "You do not need to include the forward-slash when building a regex."
so I delete the forward-slash, my code
strName = "/^" + name + ".*/";
BSON_APPEND_REGEX(cond, "name", strName.c_str(), "i");
change to
strName = "/^" + name + ".*/";
BSON_APPEND_REGEX(cond, "name", strName.c_str(), "i");
It can work. My problem has been solved.

QString replace only first occurrence

Is there simple way of replacing only first occurrence of some substring by other substring in QString? It can be at any position.
You could try this:
QString str("this is a string"); // The initial string.
QString subStr("is"); // String to replace.
QString newStr("at"); // Replacement string.
str.replace(str.indexOf(subStr), subStr.size(), newStr);
Resulting string will be:
that at a string
There is no convenience method for the operation you wish to have. However, you can use the following two methods to build your custom operation:
int QString::indexOf(const QString & str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
Returns the index position of the first occurrence of the string str in this string, searching forward from index position from. Returns -1 if str is not found.
If cs is Qt::CaseSensitive (default), the search is case sensitive; otherwise the search is case insensitive.
and
QString & QString::replace(int position, int n, const QString & after)
Replaces n characters beginning at index position with the string after and returns a reference to this string.
Note: If the specified position index is within the string, but position + n goes outside the strings range, then n will be adjusted to stop at the end of the string.
Now, putting all that into practice, you could write something as follows:
main.cpp
#include <QString>
#include <QDebug>
int main()
{
QString initialString = QLatin1String("foo bar baz");
QString fooString = QLatin1String("foo");
initialString.replace(initialString.indexOf(fooString),
fooString.size(), QLatin1String("stuff"));
qDebug() << initialString;
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Output
"stuff bar baz"
This is pretty much the way QString::replace(QRegularExpression, ... does it. Since it's possible that literal backslashes could be part of replace pattern, those need to be captured differently. Note that actual replacement happens right-to-left to preserve leftward offset validity. It's possible to put this more compactly, but easier to debug in this form.
QRegularExpression regex = QRegularExpression(regex_pattern);
if (regex.isValid() and
(regex_pattern.length() > 0)) {
QRegularExpressionMatchIterator regex_iterator =
regex.globalMatch(target_text, Apply_Target_Offset,
QRegularExpression::PartialPreferCompleteMatch);
if (regex_iterator.hasNext()) {
// At least one found
QRegularExpressionMatch match = regex_iterator.next();
if (match.hasMatch() and (not match.hasPartialMatch())) {
// This is the first match, and it's complete
int match_begin = match.capturedStart();
int match_end = match.capturedEnd();
int match_length = match.capturedLength();
QStringList captured;
const int capture_groups_count = regex.captureCount() + 1;
for (int capture_group_idx = 0; capture_group_idx < capture_groups_count; ++capture_group_idx) {
captured.append(match.captured(capture_group_idx));
}
QString replace_pattern = Apply_Replace_Pattern->toPlainText();
QString replace_text = replace_pattern;
QList<QRegularExpressionMatch> replace_pattern_match_list;
QRegularExpression replace_pattern_regex = QRegularExpression("(?:\\\\\\\\)+|(?:\\\\(\\d+))");
if (replace_pattern_regex.isValid()) {
QRegularExpressionMatchIterator replace_pattern_regex_iterator =
replace_pattern_regex.globalMatch(replace_pattern);
while (replace_pattern_regex_iterator.hasNext()) {
QRegularExpressionMatch replace_pattern_match = replace_pattern_regex_iterator.next();
bool no_error;
replace_pattern_match.captured().right(1).toInt(&no_error);
// Only accept backreferences w/ numbers
if (no_error) replace_pattern_match_list.append(replace_pattern_match);
}
while (replace_pattern_match_list.count() > 0) {
QRegularExpressionMatch replace_pattern_match = replace_pattern_match_list.takeLast();
int cap_idx = replace_pattern_match.captured(1).toInt();
if (cap_idx < captured.count()) {
replace_text.replace(replace_pattern_match.capturedStart(),
(replace_pattern_match.capturedEnd() -
replace_pattern_match.capturedStart()),
captured[cap_idx]);
}
}
// Render '\' characters properly
replace_text.replace("\\\\", "\\");
}
target_text.replace(match_begin, (match_end - match_begin), replace_text);
}
}
}
//------------------------------------------------------------------
QString & replace_first(QString &io_haystack, const QString & sub_str, const QString & new_str)
{
io_haystack.replace(io_haystack.indexOf(sub_str), sub_str.size(), new_str);
return io_haystack;
} // replace_first
//------------------------------------------------------------------
QString & replace_first(QString &io_haystack, const QRegularExpression & sub_regx, const QString & new_str)
{
QRegularExpressionMatch match;
match = sub_regx.match(io_haystack);
if (match.hasMatch()) {
QString sub_str = match.captured(0);
io_haystack.replace(io_haystack.indexOf(sub_str), sub_str.size(), new_str);
}
return io_haystack;
} // replace_first

How can i convert entity character(Escape character) to HTML in QT?

I want to convert entity character(Escape character) to HTML in QT, please help me....
i.e: I want to replace " with ", > with >
=====This is my code that not worked====
QString MyApp::ReplaceString(const QString Data, const QString &Before, const QString &After)
{
QString Result = Data;
Result.replace(Before, After, Qt::CaseInsensitive);
return Result;
}
========
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QByteArray data=pReply->readAll();
QString str = codec->toUnicode((const char *)data);
str = Qt::escape(str);
str = ReplaceString(str, """, "\"");
str = ReplaceString(str,">", ">");
I'm not sure I understand what you want, just guessing. You can use QTextDocument. Try something like this:
QTextDocument text;
text.setHtml("<>"");
QString plain = text.toPlainText();
qDebug("%s.", qPrintable(plain));
Remember that QTextDocument needs the gui module.
I think this will solve your problem.
QString escaped=
QString(myhtml).replace("&","&").replace(">",">").replace("<","<");
Test escape() function:
QString plain = "#include <QtCore>"
QString html = Qt::escape(plain);
// html == "#include <QtCore>"
and convertFromPlainText() function:
QString Qt::convertFromPlainText ( const QString & plain, WhiteSpaceMode mode = WhiteSpacePre )
Hello to convert non ASCII character to &#XXX; (where XXX is a number):
/***************************************************************************//*!
* #brief Encode all non ASCII characters into &#...;
* #param[in] src Text to analyze
* #param[in,opt] force Force the characters "list" to be converted.
* #return ASCII text compatible.
*
* #note Original code: http://www.qtforum.org/article/3891/text-encoding.html
*
* #warning Do not forget to use QString::fromUtf8()
*/
QString encodeEntities( const QString& src, const QString& force=QString() )
{
QString tmp(src);
uint len = tmp.length();
uint i = 0;
while( i<len )
{
if( tmp[i].unicode() > 128 || force.contains(tmp[i]) ){
QString rp = "&#"+QString::number(tmp[i].unicode())+";";
tmp.replace(i,1,rp);
len += rp.length()-1;
i += rp.length();
}else{
++i;
}
}
return tmp;
}
/***************************************************************************//*!
* #brief Allows decode &#...; into UNICODE (utf8) character.
* #param[in] src Text to analyze
* #return UNICODE (utf8) text.
*
* #note Do not forget to include QRegExp
*/
QString decodeEntities( const QString& src )
{
QString ret(src);
QRegExp re("&#([0-9]+);");
re.setMinimal(true);
int pos = 0;
while( (pos = re.indexIn(src, pos)) != -1 )
{
ret = ret.replace(re.cap(0), QChar(re.cap(1).toInt(0,10)));
pos += re.matchedLength();
}
return ret;
}
Basic usage:
qDebug() << encodeEntities(QString::fromUtf8("éà#<>hello the world €"),QString("<>"));
// Will print: éà#<>hello the world €
qDebug() << decodeEntities("aßéplopéàçê€");
// Will print: hello world

webcrawler link extraction problem

im writing a simple webcrawler. the problem is, with the link extraction.
i uses the cpp-netlib with boost. here a few lines of my CLink Class.
CLink::CLink(const CLink& father, const std::string& relUrl )
{
uri = relUrl;
boost::network::uri::uri instance(relUrl);
boost::network::uri::uri instanceFather(father.uri);
if ( (valid = boost::network::uri::is_valid(instance)) == 1)
{
scheme = boost::network::uri::scheme(instance);
user_info = boost::network::uri::user_info(instance);
host = boost::network::uri::host(instance);
port = boost::network::uri::port(instance);
path = boost::network::uri::path(instance);
query = boost::network::uri::query(instance);
fragment = boost::network::uri::fragment(instance);
uri = scheme;
uri += "://";
uri += host;
uri += path;
}
else
{
if ( (valid = boost::network::uri::is_valid(instanceFather)) == 1)
{
scheme = boost::network::uri::scheme(instanceFather);
user_info = boost::network::uri::user_info(instanceFather);
host = boost::network::uri::host(instanceFather);
port = boost::network::uri::port(instanceFather);
path = boost::network::uri::path(instance);
query = boost::network::uri::query(instance);
fragment = boost::network::uri::fragment(instance);
uri = scheme;
uri += "://";
uri += host;
uri += path;
}
}
};
CLink::CLink( const std::string& _url )
{
uri = _url;
boost::network::uri::uri instance(_url);
if ( (valid = boost::network::uri::is_valid(instance) ) == 1)
{
scheme = boost::network::uri::scheme(instance);
user_info = boost::network::uri::user_info(instance);
host = boost::network::uri::host(instance);
port = boost::network::uri::port(instance);
path = boost::network::uri::path(instance);
query = boost::network::uri::query(instance);
fragment = boost::network::uri::fragment(instance);
uri = scheme;
uri += "://";
uri += host;
uri += path;
}
else
std::cout << "err " << std::endl;
};
the links from the webpage i took with the htmlcxx lib. i took the HTML::Node and normalize them wih the boost filesystem.
if ( url.find("http://") == std::string::npos)
{
std::string path = link.get_path() + url;
url = link.get_host() + path;
boost::filesystem::path result;
boost::filesystem::path p(url);
for(boost::filesystem::path::iterator it=p.begin(); it!=p.end(); ++it)
{
if(*it == "..")
{
if(boost::filesystem::is_symlink(result) )
result /= *it;
else if(result.filename() == "..")
result /= *it;
else
result = result.parent_path();
}
else if(*it == ".")
{
// Ignore
}
else
{
// Just cat other path entries
result /= *it;
}
}
url = "http://" + result.string();
}
return ret;
Now the problem is.
i try to fetch http://www.wikipedia.de/ and i get the urls like
properties
http://wikimedia.de/wiki/Vereinszeitung
... ...
and on the site http://wikimedia.de/wiki/Vereinszeitung there is a link like /wiki/vereinsatzung
so often i get links like
http://wikimedia.de/wiki/Vereinszeitung/wiki/Freies_Wissen
does someone have a idee?
You need to have a special case for absolute links (those that start with /).
If the href starts with /, then the resulting link should be (using the terms from The URI template which come from the RFC):
[scheme]://[authority][what you got in href]
What you are currently constructing is:
[scheme]://[authority][path][what you got in href]
So you're duplicating the path information.
So if link.get_path() starts with /, you should simply change:
std::string path = link.get_path() + url;
url = link.get_host() + path; // this is incorrect btw, missing the [port]
to
url = link.get_host() + ":" + link.get_port() + url;
It would probably be cleaner to do the path normalization on the path only, not on the URL (i.e. add host:port after normalizing the path).
[And I think your code will fail if it encounters an https link.]

Remove '\n.\n' C++

If i have a string as such
"I am not here... \n..Hello\n.\n....Whats happening"
I want to replace the above string so:
"I am not here... \n..Hello\n. \n....Whats happening"
^ Space added
Just a bit of a background on what im doing. Im using sendmail in C++ and \n.\n is End Of Message Equivalent of sendmail. I just created a class that uses sendmail to send mails. but obviously if the user from the outsite gives sendmail that command i want it to be removed. Here is my message function just incase.:
//Operator to add to the message
void operator<<(string imessage){
if (imessage != ""){ message += imessage; }
}
How would i go about doing this. Thanks in advance :D
This is my last version :)
This code handles the case mentioned by #Greg Hewgill
string& format_text(string& str)
{
const string::size_type dot_offset = 2;
string::size_type found_at_start = str.find("\n.\n"),
found_at = str.find("\n.\n");
if(found_at_start != string::npos)
str.insert(0, " ");
while(found_at != string::npos)
{
str.insert(found_at+dot_offset+1, " ");
found_at = str.find("\n.\n", found_at+1);
}
return str;
}
int main()
{
string text = ".\nn\n.\nn";
std::cout << format_text(text);
}
Look up String.find and String.replace
For example (not tested)
string endOfMessage = "\n.\n";
string replacement = "\n. \n";
size_t position;
while (position = message.find(endOfMessage))
{
message.replace(position, endOfMessage.length(), replacement);
}
This is derived from Dan McG's answer so upvote him ;)
string endOfMessage = "\n.\n";
string replacement = "\n. \n";
size_t position;
while (position = message.find(endOfMessage, position) != message.npos)
{
message.replace(position, endOfMessage.length(), replacement);
position += replacement.length();
}
Boost has Boost.Regex (a regular expression module). Might be overkill if this is the only replacement you need to do.
Use std::search and the insert method of sequence containers such as string, deque, or whatever you use to store the message text.
typedef std::string::iterator SIter; // or whatever container you use
static const char *end_seq = "\n.\n";
for ( SIter tricky_begin = msg.begin();
tricky_begin = std::search( tricky_begin, msg.end(), end_seq, end_seq+3 ),
tricky_begin != msg.end(); ) {
tricky_begin = msg.insert( tricky_begin + 2, ' ' );
}