Returns nullptr if the general attribute pattern of ((whitespace)*attrib=value)*> isn't matched Returns Py_None if you're pointing at > already (no attributes) Returns a dict of attributes on success.
| 46 | // Returns a dict of attributes on success. |
| 47 | // |
| 48 | PyObject* ParseAttribs( wchar_t*& curPos, const wchar_t* keyAlreadyParsed = NULL ) |
| 49 | { |
| 50 | if( *curPos == L'>' ) |
| 51 | { |
| 52 | // Well, that was easy, there aren't any. |
| 53 | curPos++; |
| 54 | Py_INCREF( Py_None ); |
| 55 | return Py_None; |
| 56 | } |
| 57 | |
| 58 | enum attribStates |
| 59 | { |
| 60 | ASTATE_KEY, |
| 61 | ASTATE_VALUE, |
| 62 | ASTATE_WHITEOREND, |
| 63 | ASTATE_WHITESPACE, |
| 64 | ASTATE_TERMINATE |
| 65 | }; |
| 66 | |
| 67 | attribStates astate; |
| 68 | const wchar_t* key = nullptr; |
| 69 | PyObject* result = PyDict_New(); |
| 70 | |
| 71 | if( keyAlreadyParsed ) |
| 72 | { |
| 73 | key = keyAlreadyParsed; |
| 74 | astate = ASTATE_VALUE; |
| 75 | } |
| 76 | else |
| 77 | { |
| 78 | astate = ASTATE_WHITESPACE; |
| 79 | } |
| 80 | |
| 81 | while( astate != ASTATE_TERMINATE ) |
| 82 | { |
| 83 | switch( astate ) |
| 84 | { |
| 85 | case ASTATE_WHITEOREND: |
| 86 | if( *curPos == L'>' ) |
| 87 | { |
| 88 | curPos++; |
| 89 | astate = ASTATE_TERMINATE; |
| 90 | break; |
| 91 | } |
| 92 | // Fall through |
| 93 | case ASTATE_WHITESPACE: { |
| 94 | bool matched = false; |
| 95 | bool wasWhite = true; |
| 96 | |
| 97 | while( wasWhite ) |
| 98 | { |
| 99 | wchar_t next = *curPos; |
| 100 | if( next == L' ' || next == L'\t' ) |
| 101 | { |
| 102 | curPos++; |
| 103 | matched = true; |
| 104 | } |
| 105 | else if( next == L'&' && _wcsnicmp( curPos + 1, L"nbsp;", 5 ) == 0 ) |
no test coverage detected