How can I extract a CString between two tags ?
<tag1>My Text</tag1>
I don't want to calculate the start and end position then use Mid, maybe there is another easier method using STL ?
Disclaimer: the following idea is bad and should not be used in production code. I'm assuming you just want a quick hack for testing.
Use a regular expression to match the tags. Microsoft provides this in CAtlRegExp. If you're using Visual Studio 2008 or newer, download ATL here. Then, just provide myString to the code below:
#include "atlrx.h"
CAtlRegExp<> regex;
VERIFY( REPARSE_ERROR_OK == regex.Parse("<tag1>(.*)</tag1>") );
CAtlREMatchContext<> mc;
if (!regex.Match(myString, &mc)) {
// no match found
} else {
// match(es) found
for (UINT nGroupIndex = 0; nGroupIndex < mc.m_uNumGroups; ++nGroupIndex) {
const CAtlREMatchContext<>::RECHAR* szStart = 0;
const CAtlREMatchContext<>::RECHAR* szEnd = 0;
mc.GetMatch(nGroupIndex, &szStart, &szEnd);
ptrdiff_t nLength = szEnd - szStart;
CString text(szStart, nLength);
// now do something with text
}
}
Disclaimer 2: You really should use an XML parser library instead.
Related
When I'm retrieving a code signing signature from an executable file on Windows, the CERT_CONTEXT of the certificate points to the CERT_INFO, that has CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm member that contains the algorithm used for signing.
How do I convert that to a human readable form as such?
For instance, SignatureAlgorithm.pszObjId may be set to "1.2.840.113549.1.1.11" string, which is szOID_RSA_SHA256RSA according to this long list. I guess I can make a very long switch statement for it, and link it to "sha256", but I'd rather avoid it since I don't know what most of those values are. Is there an API that can do all that for me?
Use CryptFindOIDInfo to get information about a OID including the display name and the CNG algorithm identifier string:
void PrintSigAlgoName(CRYPT_ALGORITHM_IDENTIFIER* pSigAlgo)
{
if(pSigAlgo && pSigAlgo->pszObjId)
{
PCCRYPT_OID_INFO pCOI = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pSigAlgo->pszObjId, 0);
if(pCOI && pCOI->pwszName)
{
_tprintf(_T("%ls"), pCOI->pwszName);
}
else
{
_tprintf(_T("%hs"), pSigAlgo->pszObjId);
}
}
}
Expanding on the answer of Anders. You can also get this information from the result of a call to WinVerifyTrust(). It is deeply nested inside CRYPT_PROVIDER_DATA:
GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA trustData;
// omitted: prepare trustData
DWORD lStatus = ::WinVerifyTrust( NULL, &policyGUID, &trustData );
if( lStatus == ERROR_SUCCESS )
{
CRYPT_PROVIDER_DATA* pData = ::WTHelperProvDataFromStateData( trustData.hWVTStateData );
if( pData && pData->pPDSip && pData->pPDSip->psIndirectData &&
pData->pPDSip->psIndirectData->DigestAlgorithm.pszObjId )
{
CRYPT_ALGORITHM_IDENTIFIER const& sigAlgo = pData->pPDSip->psIndirectData->DigestAlgorithm;
PCCRYPT_OID_INFO pCOI = ::CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, sigAlgo.pszObjId, 0 );
if(pCOI && pCOI->pwszName)
{
_tprintf(_T("%ls"), pCOI->pwszName);
}
else
{
_tprintf(_T("%hs"), sigAlgo.pszObjId);
}
}
}
Note: Detailed error checking omitted for brevity!
Note2: From Win 8 onwards (and patched Win 7), WinVerifyTrust can be used to verify and get information about multiple signatures of a file, more info in this Q&A.
I have written a C++ method from which I need to return a structure to Python.
I'm already able to send an OpenCV mat from Python to C++ using BOOST following the method described in this link.
Now I need to go the other way; return from C++ to Python, and then access that structure in Python. Can it be done?
Any samples or reference links would be good. I have tried googling before posting this question and I couldn't get any samples or explanation links.
You can use another function from modules/python/src2/cv2.cpp:
PyObject* pyopencv_from(const cv::Mat& m)
{
if( !m.data )
Py_RETURN_NONE;
cv::Mat temp, *p = (cv::Mat*)&m;
if(!p->refcount || p->allocator != &g_numpyAllocator)
{
temp.allocator = &g_numpyAllocator;
m.copyTo(temp);
p = &temp;
}
p->addref();
return pyObjectFromRefcount(p->refcount);
}
Then the Boost Python wrapper will look like:
boost::python::object toPython( const cv::Mat &frame )
{
PyObject* pyObjFrame = pyopencv_from( frame );
boost::python::object boostPyObjFrame(boost::python::handle<>((PyObject*)pyObjFrame));
return boostPyObjFrame;
}
Please have a look at this link: https://wiki.python.org/moin/boost.python/handle to make sure that you use the appropriate boost::python::handle<> function for your case.
If you need don't need to return a cv::Mat but different data you might consider to use boost::python::list or boost::python::dict. For example if you want to return a vectors of 2D points to Python you can do something like:
boost::python::dict toPython( std::vector<cv::Point> newPoints, std::vector<cv::Point> oldPoints )
{
boost::python::dict pointsDict;
boost::python::list oldPointsList;
boost::python::list newPointsList;
for( size_t ii = 0; ii < oldPoints.size( ); ++ii )
{
oldPointsList.append( boost::python::make_tuple( oldPoints[ii].x, oldPoints[ii].y ) );
}
for( size_t ii = 0; ii < newPoints.size( ); ++ii )
{
newPointsList.append( boost::python::make_tuple( newPoints[ii].x, newPoints[ii].y ) );
}
pointsDict["oldPoints"] = oldPointsList;
pointsDict["newPoints"] = newPointsList;
return pointsDict
}
Finally the Boost Python wrapper:
BOOST_PYTHON_MODULE( myWrapper )
{
// necessary only if array (cv::Mat) is returned
import_array();
boost::python::converter::registry::insert( &extract_pyarray, type_id<PyArrayObject>());
def toPython("toPython", &toPython);
}
I haven't tested this specific solution but it should work in principle.
This might be a little too late, but take a look at https://github.com/spillai/numpy-opencv-converter
Given the following code I need it to work on a Korean/Japanese Windows SO.
It just dosen't work, and i cant tell why...
May You guys help me out?
void RecurseSearch(LPCTSTR pstr, CString serchTerm, CSimpleMap<CString,CString>* arr)
{
CFileFind finder;
// build a string with wildcards
CString strWildcard;
int code_point = 0x5c ;
WCHAR chr = (WCHAR) code_point;
strWildcard.Format(_T("%s%c*%s*"), pstr,chr,serchTerm);
CString actualFolder;
// start working for files
BOOL bWorking = finder.FindFile(strWildcard);
while (bWorking)
{
bWorking = finder.FindNextFile();
actualFolder=finder.GetFilePath();
// skip . and .. files; otherwise, we'd
// recur infinitely!
if (finder.IsDots())
continue;
// if it's a directory, recursively search it
else if (finder.IsDirectory())
{
CString str = finder.GetFilePath();
RecurseSearch(str, serchTerm, arr);
}
else
{
if(arr->GetSize()>200) return;
if(arr->FindKey(finder.GetFileURL())==-1)
arr->Add(finder.GetFileURL(),finder.GetFileURL());
}
}
bWorking = finder.FindFile(pstr+(CString)chr+(CString)_T("*"));
while(bWorking)
{
bWorking = finder.FindNextFile();
actualFolder =finder.GetFilePath();
if (!finder.IsDirectory() || finder.IsDots()) continue;
else
{
RecurseSearch(actualFolder, serchTerm, arr);
}
}
finder.Close();
}
this code works just fine on a American Windows, but doesn't on Korean ...
I even set the path separator to the correct unicode but nothing...
EDIT: I've identified the error, it was relative to ItemNames and ItemDisplayNames. I need to search for ItemDisplayNames but the CFindFile search for ItemName.
I change the code to use ISearchFolderItemFactory and then perform a AQS query.
TY Guys anyway!
Use backslash for the path separator. Regardless of the current language, backslash is documented as accepted in all cases. It could be MFC is screwing things up...
Here are two links that should help.
http://msdn.microsoft.com/en-us/library/dd317748(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#naming_conventions
What is the easiest/optimal way to transform AnsiString into Cyrillic using C++ STL!
in php it would be
<?php
// функция превода текста с кириллицы в траскрипт
function encodestring($st)
{
// Сначала заменяем "односимвольные" фонемы.
$st=strtr($st,"абвгдеёзийклмнопрстуфхъыэ_",
"abvgdeeziyklmnoprstufh'iei");
$st=strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ_",
"ABVGDEEZIYKLMNOPRSTUFH'IEI");
// Затем - "многосимвольные".
$st=strtr($st,
array(
"ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh",
"щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya",
"Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH",
"Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA",
"ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye"
)
);
// Возвращаем результат.
return $st;
}
?>
I prefer to use STL Containers, need help!
You may use the same code style in C++ also. Look to the std::map container. In newest standard C++11 you are also able to initialize it in a very convinient manner:
map letters =
{{ "f", "ф"},
{ "h", "х"},
//and so on
};
Finally I wrote my own func and it works well! I think it'll get my job done but not so optimized! Tried to use map.find() smth like this but .....
AnsiString Latin2Cyr(AnsiString inStr)
{
int l=inStr.Length();
if (!l) return "";
AnsiString strLat[]={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
AnsiString strCyr[]={"а","б","с","д","е","ф","г","х","и","дж","к","л","м","н","о","п","к","р","с","т","у","в","у","кс","й","з"};
AnsiString outStr="";
typedef multimap<AnsiString,AnsiString> mmp;
mmp mStr;
int ln=(sizeof(strLat))/(sizeof(AnsiString));
for (int i = 0; i < ln; i++) mStr.insert(mmp::value_type(strLat[i],strCyr[i]));
AnsiString k=""; mmp::iterator it;
for (int j = 1; j <l+1; j++) {
for ( it=mStr.begin(); it!= mStr.end();++it ){
outStr+=((*it).first==inStr.SubString(j,1))? (*it).second : k ;
}
}
return outStr;
}
any ideas to optimize it?
What is the cleanest way to recursively search for files using C++ and MFC?
EDIT: Do any of these solutions offer the ability to use multiple filters through one pass? I guess with CFileFind I could filter on *.* and then write custom code to further filter into different file types. Does anything offer built-in multiple filters (ie. *.exe,*.dll)?
EDIT2: Just realized an obvious assumption that I was making that makes my previous EDIT invalid. If I am trying to do a recursive search with CFileFind, I have to use *.* as my wildcard because otherwise subdirectories won't be matched and no recursion will take place. So filtering on different file-extentions will have to be handled separately regardless.
Using CFileFind.
Take a look at this example from MSDN:
void Recurse(LPCTSTR pstr)
{
CFileFind finder;
// build a string with wildcards
CString strWildcard(pstr);
strWildcard += _T("\\*.*");
// start working for files
BOOL bWorking = finder.FindFile(strWildcard);
while (bWorking)
{
bWorking = finder.FindNextFile();
// skip . and .. files; otherwise, we'd
// recur infinitely!
if (finder.IsDots())
continue;
// if it's a directory, recursively search it
if (finder.IsDirectory())
{
CString str = finder.GetFilePath();
cout << (LPCTSTR) str << endl;
Recurse(str);
}
}
finder.Close();
}
Use Boost's Filesystem implementation!
The recursive example is even on the filesystem homepage:
bool find_file( const path & dir_path, // in this directory,
const std::string & file_name, // search for this name,
path & path_found ) // placing path here if found
{
if ( !exists( dir_path ) ) return false;
directory_iterator end_itr; // default construction yields past-the-end
for ( directory_iterator itr( dir_path );
itr != end_itr;
++itr )
{
if ( is_directory(itr->status()) )
{
if ( find_file( itr->path(), file_name, path_found ) ) return true;
}
else if ( itr->leaf() == file_name ) // see below
{
path_found = itr->path();
return true;
}
}
return false;
}
I know it is not your question, but it is also easy to to without recursion by using a CStringArray
void FindFiles(CString srcFolder)
{
CStringArray dirs;
dirs.Add(srcFolder + "\\*.*");
while(dirs.GetSize() > 0) {
CString dir = dirs.GetAt(0);
dirs.RemoveAt(0);
CFileFind ff;
BOOL good = ff.FindFile(dir);
while(good) {
good = ff.FindNextFile();
if(!ff.IsDots()) {
if(!ff.IsDirectory()) {
//process file
} else {
//new directory (and not . or ..)
dirs.InsertAt(0,nd + "\\*.*");
}
}
}
ff.Close();
}
}
Check out the recls library - stands for recursive ls - which is a recursive search library that works on UNIX and Windows. It's a C library with adaptations to different language, including C++. From memory, you can use it something like the following:
using recls::search_sequence;
CString dir = "C:\\mydir";
CString patterns = "*.doc;abc*.xls";
CStringArray paths;
search_sequence files(dir, patterns, recls::RECURSIVE);
for(search_sequence::const_iterator b = files.begin(); b != files.end(); b++) {
paths.Add((*b).c_str());
}
It'll find all .doc files, and all .xls files beginning with abc in C:\mydir or any of its subdirectories.
I haven't compiled this, but it should be pretty close to the mark.
CString strNextFileName , strSaveLog= "C:\\mydir";
Find.FindFile(strSaveLog);
BOOL l = Find.FindNextFile();
if(!l)
MessageBox("");
strNextFileName = Find.GetFileName();
Its not working. Find.FindNextFile() returning false even the files are present in the same directory``