| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.cassandra.db.transform; |
| |
| import java.util.Arrays; |
| |
| class Stack |
| { |
| static final Stack EMPTY = new Stack(); |
| |
| Transformation[] stack; |
| int length; // number of used stack entries |
| MoreContentsHolder[] moreContents; // stack of more contents providers (if any; usually zero or one) |
| |
| // an internal placeholder for a MoreContents, storing the associated stack length at time it was applied |
| static class MoreContentsHolder |
| { |
| final MoreContents moreContents; |
| int length; |
| private MoreContentsHolder(MoreContents moreContents, int length) |
| { |
| this.moreContents = moreContents; |
| this.length = length; |
| } |
| } |
| |
| Stack() |
| { |
| stack = new Transformation[0]; |
| moreContents = new MoreContentsHolder[0]; |
| } |
| |
| Stack(Stack copy) |
| { |
| stack = copy.stack; |
| length = copy.length; |
| moreContents = copy.moreContents; |
| } |
| |
| void add(Transformation add) |
| { |
| if (length == stack.length) |
| stack = resize(stack); |
| stack[length++] = add; |
| } |
| |
| void add(MoreContents more) |
| { |
| this.moreContents = Arrays.copyOf(moreContents, moreContents.length + 1); |
| this.moreContents[moreContents.length - 1] = new MoreContentsHolder(more, length); |
| } |
| |
| private static <E> E[] resize(E[] array) |
| { |
| int newLen = array.length == 0 ? 5 : array.length * 2; |
| return Arrays.copyOf(array, newLen); |
| } |
| |
| // reinitialise the transformations after a moreContents applies |
| void refill(Stack prefix, MoreContentsHolder holder, int index) |
| { |
| // drop the transformations that were present when the MoreContents was attached, |
| // and prefix any transformations in the new contents (if it's a transformer) |
| moreContents = splice(prefix.moreContents, prefix.moreContents.length, moreContents, index, moreContents.length); |
| stack = splice(prefix.stack, prefix.length, stack, holder.length, length); |
| length += prefix.length - holder.length; |
| holder.length = prefix.length; |
| } |
| |
| private static <E> E[] splice(E[] prefix, int prefixCount, E[] keep, int keepFrom, int keepTo) |
| { |
| int keepCount = keepTo - keepFrom; |
| int newCount = prefixCount + keepCount; |
| if (newCount > keep.length) |
| keep = Arrays.copyOf(keep, newCount); |
| if (keepFrom != prefixCount) |
| System.arraycopy(keep, keepFrom, keep, prefixCount, keepCount); |
| if (prefixCount != 0) |
| System.arraycopy(prefix, 0, keep, 0, prefixCount); |
| return keep; |
| } |
| } |
| |