content: /*
   *
   * 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
  {
      public static final Transformation[] EMPTY_TRANSFORMATIONS = new Transformation[0];
      public static final MoreContentsHolder[] EMPTY_MORE_CONTENTS_HOLDERS = new MoreContentsHolder[0];
      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 = EMPTY_TRANSFORMATIONS;
          moreContents = EMPTY_MORE_CONTENTS_HOLDERS;
      }
  
      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;
      }
  }
  
  