| 1231 | } |
| 1232 | |
| 1233 | void basic_string::swapWith(basic_string& other) { |
| 1234 | if (this == &other) return; |
| 1235 | |
| 1236 | bool thisInline = isInline(); |
| 1237 | bool otherInline = other.isInline(); |
| 1238 | |
| 1239 | if (!thisInline && !otherInline) { |
| 1240 | // Both non-inline: swap variant + length |
| 1241 | fl::swap(mStorage, other.mStorage); |
| 1242 | fl::swap(mLength, other.mLength); |
| 1243 | } else if (thisInline && otherInline) { |
| 1244 | // Both inline: check capacity before swapping |
| 1245 | bool thisFits = other.mLength + 1 <= mInlineCapacity; |
| 1246 | bool otherFits = mLength + 1 <= other.mInlineCapacity; |
| 1247 | if (thisFits && otherFits) { |
| 1248 | // Both fit: swap buffer contents directly |
| 1249 | fl::size maxLen = fl::max(mLength, other.mLength); |
| 1250 | for (fl::size i = 0; i <= maxLen; ++i) { |
| 1251 | char tmp = inlineBufferPtr()[i]; |
| 1252 | inlineBufferPtr()[i] = other.inlineBufferPtr()[i]; |
| 1253 | other.inlineBufferPtr()[i] = tmp; |
| 1254 | } |
| 1255 | fl::swap(mLength, other.mLength); |
| 1256 | } else { |
| 1257 | // Capacity mismatch: promote to heap where needed |
| 1258 | NotNullStringHolderPtr thisData( |
| 1259 | fl::make_shared<StringHolder>(inlineBufferPtr(), mLength)); |
| 1260 | NotNullStringHolderPtr otherData( |
| 1261 | fl::make_shared<StringHolder>(other.inlineBufferPtr(), other.mLength)); |
| 1262 | fl::size thisLen = mLength; |
| 1263 | fl::size otherLen = other.mLength; |
| 1264 | if (thisFits) { |
| 1265 | mStorage.reset(); |
| 1266 | fl::memcpy(inlineBufferPtr(), otherData->data(), otherLen + 1); |
| 1267 | } else { |
| 1268 | mStorage = otherData; |
| 1269 | } |
| 1270 | mLength = otherLen; |
| 1271 | if (otherFits) { |
| 1272 | other.mStorage.reset(); |
| 1273 | fl::memcpy(other.inlineBufferPtr(), thisData->data(), thisLen + 1); |
| 1274 | } else { |
| 1275 | other.mStorage = thisData; |
| 1276 | } |
| 1277 | other.mLength = thisLen; |
| 1278 | } |
| 1279 | } else if (thisInline) { |
| 1280 | // this inline, other non-inline |
| 1281 | fl::size thisLen = mLength; |
| 1282 | // Take other's non-inline storage |
| 1283 | mStorage = fl::move(other.mStorage); |
| 1284 | mLength = other.mLength; |
| 1285 | // Put this's old inline data into other |
| 1286 | other.mStorage.reset(); |
| 1287 | if (thisLen + 1 <= other.mInlineCapacity) { |
| 1288 | fl::memcpy(other.inlineBufferPtr(), inlineBufferPtr(), thisLen + 1); |
| 1289 | } else { |
| 1290 | other.mStorage = NotNullStringHolderPtr( |