| 502 | |
| 503 | |
| 504 | ResultType Var::AssignString(LPCTSTR aBuf, VarSizeType aLength, bool aExactSize) |
| 505 | // Returns OK or FAIL. |
| 506 | // If aBuf isn't NULL, caller must ensure that aLength is either VARSIZE_MAX (which tells us that the |
| 507 | // entire strlen() of aBuf should be used) or an explicit length (can be zero) that the caller must |
| 508 | // ensure is less than or equal to the total length of aBuf (if less, only a substring is copied). |
| 509 | // If aBuf is NULL, the variable will be set up to handle a string of at least aLength |
| 510 | // in length. In addition, if the var is the clipboard, it will be prepared for writing. |
| 511 | // Any existing contents of this variable will be destroyed regardless of whether aBuf is NULL. |
| 512 | // Note that aBuf's memory can safely overlap with that of this->Contents() because in that case the |
| 513 | // new length of the contents will always be less than or equal to the old length, and thus no |
| 514 | // reallocation/expansion is needed (such an expansion would free the source before it could be |
| 515 | // written to the destination). This is because callers pass in an aBuf that is either: |
| 516 | // 1) Between this->Contents() and its terminator. |
| 517 | // 2) Equal to this->Contents() but with aLength passed in as shorter than this->Length(). |
| 518 | // |
| 519 | // Caller can omit both params to set a var to be empty-string, but in that case, if the variable |
| 520 | // is of large capacity, its memory will not be freed. This is by design because it allows the |
| 521 | // caller to exploit its knowledge of whether the var's large capacity is likely to be needed |
| 522 | // again in the near future, thus reducing the expected amount of memory fragmentation. |
| 523 | // To explicitly free the memory, use Assign(""). |
| 524 | { |
| 525 | if (mType == VAR_ALIAS) |
| 526 | // For maintainability, it seems best not to use the following method: |
| 527 | // Var &var = *(mType == VAR_ALIAS ? mAliasFor : this); |
| 528 | // If that were done, bugs would be easy to introduce in a long function like this one |
| 529 | // if your forget at use the implicit "this" by accident. So instead, just call self. |
| 530 | return mAliasFor->AssignString(aBuf, aLength, aExactSize); |
| 531 | |
| 532 | bool do_assign = true; // Set defaults. |
| 533 | bool free_it_if_large = true; // |
| 534 | if (!aBuf) |
| 535 | if (aLength == VARSIZE_MAX) // Caller omitted this param too, so it wants to assign empty string. |
| 536 | { |
| 537 | free_it_if_large = false; |
| 538 | aLength = 0; // aBuf is set to "" further below. |
| 539 | } |
| 540 | else // Caller gave a NULL buffer to signal us to ensure the var is at least aLength in capacity. |
| 541 | do_assign = false; |
| 542 | else // Caller provided a non-NULL buffer. |
| 543 | if (aLength == VARSIZE_MAX) // Caller wants us to determine its length. |
| 544 | aLength = (mCharContents == aBuf) ? _CharLength() : (VarSizeType)_tcslen(aBuf); // v1.0.45: Added optimization check: (mContents == aBuf). v1.1.09.03: Replaced CharLength() with _CharLength() to avoid updating contents (probably only applicable when aBuf == Var::sEmptyString). |
| 545 | //else leave aLength as the caller-specified value in case it's explicitly shorter than the apparent length. |
| 546 | if (!aBuf) |
| 547 | aBuf = _T(""); // From here on, make sure it's the empty string for all uses (read-only empty string vs. sEmptyString seems more appropriate in this case). |
| 548 | |
| 549 | size_t space_needed = aLength + 1; // +1 for the zero terminator. |
| 550 | size_t space_needed_in_bytes = space_needed * sizeof(TCHAR); |
| 551 | |
| 552 | if (mType == VAR_VIRTUAL) |
| 553 | { |
| 554 | if (do_assign) |
| 555 | return AssignVirtual(ExprTokenType(const_cast<LPTSTR>(aBuf), aLength)); |
| 556 | // Since above didn't return, the caller wants to allocate some temporary memory for |
| 557 | // writing the value into, and should call Close() in order to commit the actual value. |
| 558 | } |
| 559 | else if (mType == VAR_CONSTANT) // Might be impossible due to prior validation of assignments/output vars. |
| 560 | return g_script.VarIsReadOnlyError(this); |
| 561 |
no test coverage detected