| 134 | } |
| 135 | |
| 136 | ResultType Map::SetItems(ExprTokenType *aParam[], int aParamCount) |
| 137 | { |
| 138 | ASSERT(!(aParamCount & 1)); // Caller should verify and throw. |
| 139 | |
| 140 | if (!aParamCount) |
| 141 | return OK; |
| 142 | |
| 143 | // Calculate the maximum number of items that will exist after all items are added. |
| 144 | // There may be an excess if some items already exist, so instead of allocating this |
| 145 | // exact amount up front, postpone it until the last possible moment. |
| 146 | index_t max_capacity_required = mCapacity + (aParamCount >> 1); |
| 147 | |
| 148 | for (int i = 0; i + 1 < aParamCount; i += 2) |
| 149 | { |
| 150 | if (aParam[i]->symbol == SYM_MISSING || aParam[i+1]->symbol == SYM_MISSING) |
| 151 | continue; // For simplicity. |
| 152 | |
| 153 | // See comments above. HasItem() is checked so that the capacity won't be expanded |
| 154 | // unnecessarily if all of the remaining items already exist. This produces smaller |
| 155 | // code than inlining FindItem()/Assign() here and benchmarks faster than allowing |
| 156 | // unnecessary expansion for a case like Map('c',x,'b',x,'a',x).set('a',y,'b',y). |
| 157 | if (mCapacity == mCount && !HasItem(*aParam[i])) |
| 158 | SetInternalCapacity(max_capacity_required); |
| 159 | |
| 160 | if (!SetItem(*aParam[i], *aParam[i + 1])) |
| 161 | return FAIL; // Out of memory. |
| 162 | } |
| 163 | |
| 164 | return OK; |
| 165 | } |
| 166 | |
| 167 | |
| 168 | // |