| 447 | } |
| 448 | |
| 449 | void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const |
| 450 | { |
| 451 | solAssert(_type.location() == DataLocation::Storage, ""); |
| 452 | solAssert(_type.isDynamicallySized(), ""); |
| 453 | if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32) |
| 454 | solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); |
| 455 | |
| 456 | if (_type.isByteArrayOrString()) |
| 457 | { |
| 458 | // We almost always just add 2 (length of byte arrays is shifted left by one) |
| 459 | // except for the case where we transition from a short byte array |
| 460 | // to a long byte array, there we have to copy. |
| 461 | // This happens if the length is exactly 31, which means that the |
| 462 | // lowest-order byte (we actually use a mask with fewer bits) must |
| 463 | // be (31*2+0) = 62 |
| 464 | |
| 465 | m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1; |
| 466 | m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1); |
| 467 | m_context.appendInlineAssembly(R"({ |
| 468 | // We have to copy if length is exactly 31, because that marks |
| 469 | // the transition between in-place and out-of-place storage. |
| 470 | switch length |
| 471 | case 31 |
| 472 | { |
| 473 | mstore(0, ref) |
| 474 | let data_area := keccak256(0, 0x20) |
| 475 | sstore(data_area, and(data, not(0xff))) |
| 476 | // Set old length in new format (31 * 2 + 1) |
| 477 | data := 63 |
| 478 | } |
| 479 | sstore(ref, add(data, 2)) |
| 480 | // return new length in ref |
| 481 | ref := add(length, 1) |
| 482 | })", {"ref", "data", "length"}); |
| 483 | m_context << Instruction::POP << Instruction::POP; |
| 484 | } |
| 485 | else |
| 486 | m_context.appendInlineAssembly(R"({ |
| 487 | let new_length := add(sload(ref), 1) |
| 488 | sstore(ref, new_length) |
| 489 | ref := new_length |
| 490 | })", {"ref"}); |
| 491 | } |
| 492 | |
| 493 | void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const |
| 494 | { |
no test coverage detected