text: /* 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.
   */
  
  #define C_CFISH_MEMORY
  #define CFISH_USE_SHORT_NAMES
  
  #include "charmony.h"
  
  #include <stdlib.h>
  #include <stdio.h>
  
  #include "Clownfish/Util/Memory.h"
  
  void*
  Memory_wrapped_malloc(size_t count) {
      void *pointer = malloc(count);
      if (pointer == NULL && count != 0) {
          fprintf(stderr, "Can't malloc %" PRIu64 " bytes.\n", (uint64_t)count);
          exit(1);
      }
      return pointer;
  }
  
  void*
  Memory_wrapped_calloc(size_t count, size_t size) {
      void *pointer = calloc(count, size);
      if (pointer == NULL && count != 0) {
          fprintf(stderr, "Can't calloc %" PRIu64 " elements of size %" PRIu64 ".\n",
                  (uint64_t)count, (uint64_t)size);
          exit(1);
      }
      return pointer;
  }
  
  void*
  Memory_wrapped_realloc(void *ptr, size_t size) {
      void *pointer = realloc(ptr, size);
      if (pointer == NULL && size != 0) {
          fprintf(stderr, "Can't realloc %" PRIu64 " bytes.\n", (uint64_t)size);
          exit(1);
      }
      return pointer;
  }
  
  void
  Memory_wrapped_free(void *ptr) {
      free(ptr);
  }
  
  size_t
  Memory_oversize(size_t minimum, size_t width) {
      // For larger arrays, grow by an excess of 1/8; grow faster when the array
      // is small.
      size_t extra = minimum / 8;
      if (extra < 3) {
          extra = 3;
      }
      size_t amount = minimum + extra;
  
      // Detect wraparound and return SIZE_MAX instead.
      if (amount + 7 < minimum) {
          return SIZE_MAX;
      }
  
      // Round up for small widths so that the number of bytes requested will be
      // a multiple of the machine's word size.
      if (sizeof(size_t) == 8) { // 64-bit
          switch (width) {
              case 1:
                  amount = (amount + 7) & INT64_C(0xFFFFFFFFFFFFFFF8);
                  break;
              case 2:
                  amount = (amount + 3) & INT64_C(0xFFFFFFFFFFFFFFFC);
                  break;
              case 4:
                  amount = (amount + 1) & INT64_C(0xFFFFFFFFFFFFFFFE);
                  break;
              default:
                  break;
          }
      }
      else { // 32-bit
          switch (width) {
              case 1:
                  amount = (amount + 3) & ((size_t)0xFFFFFFFC);
                  break;
              case 2:
                  amount = (amount + 1) & ((size_t)0xFFFFFFFE);
                  break;
              default:
                  break;
          }
      }
  
      return amount;
  }
  
  
  