| 1135 | } |
| 1136 | |
| 1137 | static bool ReadAttribute(std::string *name, std::string *type, |
| 1138 | std::vector<unsigned char> *data, size_t *marker_size, |
| 1139 | const char *marker, size_t size) { |
| 1140 | size_t name_len = strnlen(marker, size); |
| 1141 | if (name_len == size) { |
| 1142 | // String does not have a terminating character. |
| 1143 | return false; |
| 1144 | } |
| 1145 | *name = std::string(marker, name_len); |
| 1146 | |
| 1147 | marker += name_len + 1; |
| 1148 | size -= name_len + 1; |
| 1149 | |
| 1150 | size_t type_len = strnlen(marker, size); |
| 1151 | if (type_len == size) { |
| 1152 | return false; |
| 1153 | } |
| 1154 | *type = std::string(marker, type_len); |
| 1155 | |
| 1156 | marker += type_len + 1; |
| 1157 | size -= type_len + 1; |
| 1158 | |
| 1159 | if (size < sizeof(uint32_t)) { |
| 1160 | return false; |
| 1161 | } |
| 1162 | |
| 1163 | uint32_t data_len; |
| 1164 | memcpy(&data_len, marker, sizeof(uint32_t)); |
| 1165 | tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); |
| 1166 | |
| 1167 | if (data_len == 0) { |
| 1168 | if ((*type).compare("string") == 0) { |
| 1169 | // Accept empty string attribute. |
| 1170 | |
| 1171 | marker += sizeof(uint32_t); |
| 1172 | size -= sizeof(uint32_t); |
| 1173 | |
| 1174 | *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t); |
| 1175 | |
| 1176 | data->resize(1); |
| 1177 | (*data)[0] = '\0'; |
| 1178 | |
| 1179 | return true; |
| 1180 | } else { |
| 1181 | return false; |
| 1182 | } |
| 1183 | } |
| 1184 | |
| 1185 | marker += sizeof(uint32_t); |
| 1186 | size -= sizeof(uint32_t); |
| 1187 | |
| 1188 | if (size < data_len) { |
| 1189 | return false; |
| 1190 | } |
| 1191 | |
| 1192 | data->resize(static_cast<size_t>(data_len)); |
| 1193 | memcpy(&data->at(0), marker, static_cast<size_t>(data_len)); |
| 1194 | |