IContentBase& Content::GetContent(IContentFactory &type, std::string path) { // Transform the string so we can avoid duplicates better std::transform(path.begin(), path.end(), path.begin(), ::tolower); // Check if it already exists, if yes return it for (ContentEntry &entry : m_ContentList) { // Same Type? if (entry.Type == type.GetTypeName()) { // Same Path? if (entry.Path == path) { // And Return it return *entry.C; } } } // Since it doesn't exist, create it ContentEntry contentEntry( type.GetTypeName(), path, type.New(path) ); // Add it to the list m_ContentList.push_back(contentEntry); // Log it m_Logger.LogInfo("Loaded new %s: %s", type.GetTypeName(), path.c_str()); // And Return it return *contentEntry.C; }
PyObject * PyPreprocessor_scanHeaders( PyPreprocessor * self, PyObject * args, PyObject * kwds ) { static char * kwlist[] = { "pp_ctx", "filename", NULL }; PyObject * pObject = 0; PyObject * filename = 0; assert( self->pp ); if ( !PyArg_ParseTupleAndKeywords( args, kwds, "OO", kwlist, &pObject, &filename ) ) return NULL; if ( !pObject || ( (PyTypeObject *)PyObject_Type( pObject ) != &PyPreprocessingContextType ) ) { PyErr_SetString( PyExc_Exception, "Invalid preprocessing context parameter." ); return NULL; } PyPreprocessingContext const * ppContext( reinterpret_cast<PyPreprocessingContext *>( pObject ) ); if ( filename && !PyUnicode_Check( filename ) ) { PyErr_SetString( PyExc_Exception, "Expected a string as 'filename' parameter." ); return NULL; } Headers headers; HeaderList missing; PyThreadState * _save; bool result; try { Py_UNBLOCK_THREADS result = self->pp->scanHeaders( *ppContext->ppContext, PyUnicode_AsUTF8( filename ), headers, missing ); } catch ( std::runtime_error const & error ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_RuntimeError, error.what() ); return NULL; } catch ( std::exception const & error ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_Exception, error.what() ); return NULL; } catch ( ... ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_Exception, "Unhandled exception" ); return NULL; } if ( !result ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_Exception, "Failed to preprocess file." ); return NULL; } // Group result by dir. typedef std::vector<Header const *> HeaderPtrList; typedef std::unordered_map<Dir, HeaderPtrList> DirsAndHeaders; DirsAndHeaders dirsAndHeaders; for ( Header const & header : headers ) dirsAndHeaders[ header.dir ].push_back( &header ); Py_BLOCK_THREADS PyObject * dirsTuple = PyTuple_New( dirsAndHeaders.size() ); std::size_t dirIndex( 0 ); for ( DirsAndHeaders::value_type const & dirAndHeaders : dirsAndHeaders ) { PyObject * headersInDirTuple = PyTuple_New( dirAndHeaders.second.size() ); std::size_t headersInDirTupleIndex( 0 ); for ( Header const * header : dirAndHeaders.second ) { PyObject * headerEntry = PyTuple_New( 3 ); PyTuple_SET_ITEM( headerEntry, 0, PyUnicode_FromStringAndSize( header->name.get().data(), header->name.get().size() ) ); PyObject * const isRelative( header->relative ? Py_True : Py_False ); Py_INCREF( isRelative ); PyTuple_SET_ITEM( headerEntry, 1, isRelative ); PyContentEntry * contentEntry( (PyContentEntry *)_PyObject_New( &PyContentEntryType ) ); contentEntry->ptr = header->contentEntry.get(); intrusive_ptr_add_ref( contentEntry->ptr ); PyTuple_SET_ITEM( headerEntry, 2, (PyObject *)contentEntry ); PyTuple_SET_ITEM( headersInDirTuple, headersInDirTupleIndex++, headerEntry ); } PyObject * dirTuple = PyTuple_New( 2 ); llvm::StringRef const dirStr( dirAndHeaders.first.get() ); PyObject * dir = PyUnicode_FromStringAndSize( dirStr.data(), dirStr.size() ); PyTuple_SET_ITEM( dirTuple, 0, dir ); PyTuple_SET_ITEM( dirTuple, 1, headersInDirTuple ); PyTuple_SET_ITEM( dirsTuple, dirIndex++, dirTuple ); } PyObject * missingHeadersTuple = PyTuple_New( missing.size() ); std::size_t missingIndex( 0 ); for ( HeaderList::value_type const & missingHeader : missing ) { PyObject * val = PyUnicode_FromStringAndSize( missingHeader.data(), missingHeader.size() ); PyTuple_SET_ITEM( missingHeadersTuple, missingIndex++, val ); } PyObject * resultTuple = PyTuple_New( 2 ); PyTuple_SET_ITEM( resultTuple, 0, dirsTuple ); PyTuple_SET_ITEM( resultTuple, 1, missingHeadersTuple ); return resultTuple; }