| 1015 | } |
| 1016 | |
| 1017 | status_t XMLNode::flatten(const sp<AaptFile>& dest, |
| 1018 | bool stripComments, bool stripRawValues) const |
| 1019 | { |
| 1020 | StringPool strings(mUTF8); |
| 1021 | Vector<uint32_t> resids; |
| 1022 | |
| 1023 | // First collect just the strings for attribute names that have a |
| 1024 | // resource ID assigned to them. This ensures that the resource ID |
| 1025 | // array is compact, and makes it easier to deal with attribute names |
| 1026 | // in different namespaces (and thus with different resource IDs). |
| 1027 | collect_resid_strings(&strings, &resids); |
| 1028 | |
| 1029 | // Next collect all remainibng strings. |
| 1030 | collect_strings(&strings, &resids, stripComments, stripRawValues); |
| 1031 | |
| 1032 | #if 0 // No longer compiles |
| 1033 | NOISY(printf("Found strings:\n"); |
| 1034 | const size_t N = strings.size(); |
| 1035 | for (size_t i=0; i<N; i++) { |
| 1036 | printf("%s\n", String8(strings.entryAt(i).string).string()); |
| 1037 | } |
| 1038 | ); |
| 1039 | #endif |
| 1040 | |
| 1041 | sp<AaptFile> stringPool = strings.createStringBlock(); |
| 1042 | NOISY(aout << "String pool:" |
| 1043 | << HexDump(stringPool->getData(), stringPool->getSize()) << endl); |
| 1044 | |
| 1045 | ResXMLTree_header header; |
| 1046 | memset(&header, 0, sizeof(header)); |
| 1047 | header.header.type = htods(RES_XML_TYPE); |
| 1048 | header.header.headerSize = htods(sizeof(header)); |
| 1049 | |
| 1050 | const size_t basePos = dest->getSize(); |
| 1051 | dest->writeData(&header, sizeof(header)); |
| 1052 | dest->writeData(stringPool->getData(), stringPool->getSize()); |
| 1053 | |
| 1054 | // If we have resource IDs, write them. |
| 1055 | if (resids.size() > 0) { |
| 1056 | const size_t resIdsPos = dest->getSize(); |
| 1057 | const size_t resIdsSize = |
| 1058 | sizeof(ResChunk_header)+(sizeof(uint32_t)*resids.size()); |
| 1059 | ResChunk_header* idsHeader = (ResChunk_header*) |
| 1060 | (((const uint8_t*)dest->editData(resIdsPos+resIdsSize))+resIdsPos); |
| 1061 | idsHeader->type = htods(RES_XML_RESOURCE_MAP_TYPE); |
| 1062 | idsHeader->headerSize = htods(sizeof(*idsHeader)); |
| 1063 | idsHeader->size = htodl(resIdsSize); |
| 1064 | uint32_t* ids = (uint32_t*)(idsHeader+1); |
| 1065 | for (size_t i=0; i<resids.size(); i++) { |
| 1066 | *ids++ = htodl(resids[i]); |
| 1067 | } |
| 1068 | } |
| 1069 | |
| 1070 | flatten_node(strings, dest, stripComments, stripRawValues); |
| 1071 | |
| 1072 | void* data = dest->editData(); |
| 1073 | ResXMLTree_header* hd = (ResXMLTree_header*)(((uint8_t*)data)+basePos); |
| 1074 | size_t size = dest->getSize()-basePos; |