libxml xmlNodeDump encoding issue - libxml2

I have this code
if(genericPtr->type == XML_ATTRIBUTE_NODE){
xmlAttrPtr attr = (xmlAttrPtr)genericPtr;
printf("\n str %s\n", (const char *)attr->children->content);
}
xmlBufferPtr bufferPtr = xmlBufferCreate();
if (IsXmlNsPtr(genericPtr)){
xmlNodeDump(bufferPtr, NULL, (xmlNodePtr)genericPtr, 0, format);
}else{
xmlNodeDump(bufferPtr, ((xmlStdPtr)genericPtr)->doc, (xmlNodePtr)genericPtr, 0, format);
}
printf("\n str2 %s\n", (const char *)bufferPtr->content);
The result is
str чатрум#muc.chat.quickblox.com/300
str2 to="чатрум#muc.chat.quickblox.com/300"
In result i need чатрум instead
чатрум
how can i do this?

Try xmlNodeDumpOutput which allows you to specify an encoding. Note that it uses an xmlOutputBuffer instead of an xmlBuffer. Another useful function is xmlXPathCastNodeToString which returns the XPath string value of a node as xmlChar.

Related

How to execute multi parameter ODBC command by C++

I'm working on an ODBC program that needs to store two types of long data: nvarchar (max) and nvarbinary (max). It works well when I do it with one parameter, but it gives an error for two parameters. secound loop for SQL_NEED_DATA gives odbc error
ERROR ==> [ODBC SQL Server Driver]Invalid character value for cast specification
.My code is as follows:
bool ExecuteQuery(wstring const& command_text,vector<void*> params)
{
SQLWCHAR* blob = nullptr;// (SQLWCHAR*)params[0];
SQLSMALLINT NumParams;
SQLSMALLINT i, sql_type, decimals, nullable, paramNo;
SQLULEN bytes;
RETCODE retcode;
SQLLEN cbTextSize, valueMax = 0;
vector<SQLLEN> lbytes;
PTR pParamID;
SQLLEN len;
vector<SDWORD> cbBatch;
SQLPOINTER pToken = NULL;
retcode = SQLPrepare(hstmt, (SQLWCHAR*)command_text.c_str(), SQL_NTS);
//Get number of parameters
SQLNumParams(hstmt, &NumParams);
for (i = 0; i < NumParams; i++)
{
size_t length = wcslen((wchar_t*)params[i]);
//This ia important to save all data to sql table
size_t size = length * sizeof(wchar_t);
len = SQL_LEN_DATA_AT_EXEC((SQLLEN)size);
retcode = SQLDescribeParam(hstmt, i + 1, &sql_type, &bytes, &decimals, &nullable);
//SQL_C_WCHAR for hex binary data in wchar_t and SQL_WLONGVARCHAR succeeded
short c_type = map_datatype_SQL_to_C(sql_type);
retcode = SQLBindParameter(hstmt, i + 1, INPUT, c_type, sql_type, bytes, decimals, (PTR)(1+i), 0, &len);
}
//Execute the insert query.
retcode = SQLExecute(hstmt);
// Check for EOD marker.
retcode = SQLParamData(hstmt, &pToken);
//Loop, sending the data in segments of 124
int buffer_size = sizeof(wchar_t);
int chunk = 124;
for (i = 0; i < NumParams; i++)
{
size_t length = wcslen((wchar_t*)params[i]);
blob = (wchar_t*)params[i];
while (retcode == SQL_NEED_DATA)
{
while (length > chunk)
{
retcode = SQLPutData(hstmt, blob, static_cast<SQLLEN>(chunk * buffer_size));
extract_error("", hstmt, SQL_HANDLE_STMT);
blob += chunk;
length -= chunk;
}
retcode = SQLPutData(hstmt, blob, length * buffer_size);
extract_error("", hstmt, SQL_HANDLE_STMT);
}
retcode = SQLParamData(hstmt, &pToken);
}
return SQL_SUCCEEDED(retcode);
}
short map_datatype_SQL_to_C(short sql_type)
{
switch (sql_type)
{
case SQL_TINYINT:return SQL_C_TINYINT;
case SQL_LONGVARBINARY://-4
case SQL_VARBINARY://-3
case SQL_WLONGVARCHAR://-10
case SQL_WVARCHAR: //-9
case SQL_WCHAR: //-8
return SQL_C_WCHAR;// = SQL_C_TCHAR -8
case SQL_BIT:return SQL_C_BIT;
case SQL_BINARY://-2
return SQL_C_BINARY;
case SQL_DOUBLE://8 - FLOAT, DOUBLE
return SQL_C_DOUBLE;
case SQL_SMALLINT://5
return SQL_C_SHORT;
case SQL_FLOAT://6
case SQL_REAL: //7
return SQL_C_FLOAT;//7
case SQL_INTEGER://4
return SQL_C_LONG;
case SQL_CHAR://1
case SQL_VARCHAR://12
case SQL_DECIMAL://3
case SQL_NUMERIC://2
return SQL_C_CHAR;// CHAR, VARCHAR, DECIMAL, NUMERIC
case SQL_TYPE_TIMESTAMP:return SQL_C_TIMESTAMP;
case SQL_TIME:return SQL_C_TIME;
case SQL_DATE:return SQL_C_DATE;
case SQL_GUID:return SQL_C_GUID;
default:return SQL_UNKNOWN_TYPE;
}
return 0;
}

how to return a pointer in a function returning char *?

I'm implementing my own strrchr - it searches for the last occurrence of the character c (an unsigned char) in the string pointed to by the argument str.
example:
Input: f("abcabc" , "b")
Output: "bc"
the function should return char *. How can i return a pointer to the char array in the function?
#include <stdio.h>
#include <string.h>
char* my_strrchr(char* param_1, char param_2)
{
int len = strlen(param_1);
char res ;
for(int i = len; i >= 0 ;i-- ){
if (param_1[i] == param_2){
res = param_1[i];
return *(res);
//here i tried return (char) res, (char*) res; nothing works
}
}
return NULL;
}
int main(){
char *d = "abcabc";
char r = 'b';
my_strrchr(d, r);
return 0 ;
}
You're trying to return value, not a pointer. Operator * means to get value by a pointer, when res isn't a pointer. You should make it a pointer an then return:
char* my_strrchr(char* param_1, char param_2)
{
int len = strlen(param_1);
char *res ; //make it a pointer
for(int i = len; i >= 0 ;i-- ){
if (param_1[i] == param_2){
res = &param_1[i]; //store address of an element to a pointer
return res; //return a pointer
}
}
return NULL;
}
Your variable res is of type char. To get the reference use the reference operator & (See Meaning of "referencing" and "dereferencing" in C):
return &res
However this will result in the address of your variable res and not in the address within your param_1 array. Have a look at Alex' answer to get the correct reference address: https://stackoverflow.com/a/61930295/6669161

how to tokenize a string in arduino

i am using arduino due. what i am trying to do is to receive a string at serial. like this one:
COMSTEP 789 665 432 END
if the string starts with comstep, then to tokenize the string and get an integer array {789, 665, 432}.
is there anyway to do that?
P.S: im a noob at programming, so any help is appreciated.
I have a function that I wrote long ago to parse strings up in an easy manner. It is in use on several of my Arduino projects.
Sample usage:
char pinStr[3];
char valueStr[7];
int pinNumber, value;
getstrfld (parms_in, 0, 0, (char *)",", pinStr);
getstrfld (parms_in, 1, 0, (char *)",", valueStr);
pinNumber = atoi (pinStr);
value = atoi (valueStr);
The functions:
// My old stand-by to break delimited strings up.
char * getstrfld (char *strbuf, int fldno, int ofset, char *sep, char *retstr)
{
char *offset, *strptr;
int curfld;
offset = strptr = (char *)NULL;
curfld = 0;
strbuf += ofset;
while (*strbuf) {
strptr = !offset ? strbuf : offset;
offset = strpbrk ((!offset ? strbuf : offset), sep);
if (offset) {
offset++;
} else if (curfld != fldno) {
*retstr = 0;
break;
}
if (curfld == fldno) {
strncpy (retstr, strptr,
(int)(!offset ? strlen (strptr)+ 1 :
(int)(offset - strptr)));
if (offset)
retstr[offset - strptr - 1] = 0;
break;
}
curfld++;
}
return retstr;
}
// Included because strpbrk is not in the arduino gcc/g++ libraries
// Or I just could not find it :)
char * strpbrk (const char *s1, const char *s2)
{
const char *c = s2;
if (!*s1) {
return (char *) NULL;
}
while (*s1) {
for (c = s2; *c; c++) {
if (*s1 == *c)
break;
}
if (*c)
break;
s1++;
}
if (*c == '\0')
s1 = NULL;
return (char *) s1;
}
A light-weight approach (no strict checks on valid parses of the integers and ignoring any list elements past a fixed maximum):
char buf[32] = "COMSTEP 789 665 432 END"; // assume this has just been read
int res[8], nres = 0;
bool inlist = false;
for (char *p = strtok(buf, " "); p; p = strtok(0, " "))
if (inlist)
{
if (!strcmp(p, "END"))
{
inlist = false;
break;
}
else if (nres < sizeof(res) / sizeof(*res))
res[nres++] = atoi(p);
}
else if (!strcmp(p, "COMSTEP"))
inlist = true;
if (!inlist)
for (size_t i = 0; i < nres; ++i)
printf("%d%s", res[i], i + 1 < nres ? " " : "\n"); // do whatever

Solving QT's QString arg() ambiguity

There is an issue using QString::arg() when a string contains a digit right after a place marker. It's not clear from the QString::arg() function description what would happen in case of such a replacement:
QString("String for replacement %1234").arg("blah");
Will this result in "String for replacement blah234" or "String for replacement blah34"?
I looked in the QT's source code to answer this question. It seems that the algorithm which looks for place markers is 'greedy' and it would take both digits in the example above.
Here is the source of the QT's function which is used inside the QString::arg() (QT 4.8.4):
static ArgEscapeData findArgEscapes(const QString &s)
{
const QChar *uc_begin = s.unicode();
const QChar *uc_end = uc_begin + s.length();
ArgEscapeData d;
d.min_escape = INT_MAX;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
const QChar *c = uc_begin;
while (c != uc_end) {
while (c != uc_end && c->unicode() != '%')
++c;
if (c == uc_end)
break;
const QChar *escape_start = c;
if (++c == uc_end)
break;
bool locale_arg = false;
if (c->unicode() == 'L') {
locale_arg = true;
if (++c == uc_end)
break;
}
if (c->digitValue() == -1)
continue;
int escape = c->digitValue();
++c;
if (c != uc_end && c->digitValue() != -1) {
escape = (10 * escape) + c->digitValue();
++c;
}
if (escape > d.min_escape)
continue;
if (escape < d.min_escape) {
d.min_escape = escape;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
}
++d.occurrences;
if (locale_arg)
++d.locale_occurrences;
d.escape_len += c - escape_start;
}
return d;
}
Is there a better way of solving such an ambiguity than always using a 2-digit place markers?
Since you can only use %1 to %99 as markers and you can skip marker numbers you can write:
QString("String for replacement %10234").arg("blah");
to output String for replacement blah234
Qt help states for arg(const QString & a, int fieldWidth = 0, QChar fillChar = QLatin1Char( ' ' ))
Returns a copy of this string with the lowest numbered place marker replaced by string a, i.e., %1, %2, ..., %99.
...
Place marker numbers must be in the range 1 to 99.
Therefore, what you're seeing is, by definition, correct; the first two numbers will be replaced. If you're wanting "String for replacement blah234", then you could define the string as: -
QString("String for replacement %1%2").arg("blah").arg(234);
I have the same issue, but the order answers not looks like a good way for me.
I have resolve the ambiguity in this way.
QString myString= QString("ConcatenatedNumbers%0123").arg(66,3,10, QChar('0'));
The string will be:
ConcatenatedNumbers06623

QT QBytearray count character

How I can count characters in QByteArray, for example I have QByteArray and I want to know how many "*" in this array.
From QByteArray documentation:
int QByteArray::count ( const char * str ) const
This is an overloaded function.
Returns the number of (potentially overlapping) occurrences of string str in the byte array.
count.
You could use QByteArray::indexOf(char ch, int from = 0) const inside a loop.
Maybe this:
int i = 0, counter = 0;
while((i = array.indexOf("*", i)) >= 0)
counter++;

Resources