//===------------------------------------------------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #import #import #import #import #import #import #import #import #import "FoundationShimSupport.h" #import "NSCalendarShims.h" #import "NSCharacterSetShims.h" #import "NSCoderShims.h" #import "NSDataShims.h" #import "NSDictionaryShims.h" #import "NSErrorShims.h" #import "NSFileManagerShims.h" #import "NSIndexPathShims.h" #import "NSIndexSetShims.h" #import "NSKeyedArchiverShims.h" #import "NSLocaleShims.h" #import "NSTimeZoneShims.h" #import "NSUndoManagerShims.h" typedef struct { void *_Nonnull memory; size_t capacity; _Bool onStack; } _ConditionalAllocationBuffer; static inline _Bool _resizeConditionalAllocationBuffer(_ConditionalAllocationBuffer *_Nonnull buffer, size_t amt) { size_t amount = malloc_good_size(amt); if (amount <= buffer->capacity) { return true; } void *newMemory; if (buffer->onStack) { newMemory = malloc(amount); if (newMemory == NULL) { return false; } memcpy(newMemory, buffer->memory, buffer->capacity); buffer->onStack = false; } else { newMemory = realloc(buffer->memory, amount); if (newMemory == NULL) { return false; } } if (newMemory == NULL) { return false; } buffer->memory = newMemory; buffer->capacity = amount; return true; } static inline _Bool _withStackOrHeapBuffer(size_t amount, void (__attribute__((noescape)) ^ _Nonnull applier)(_ConditionalAllocationBuffer *_Nonnull)) { _ConditionalAllocationBuffer buffer; buffer.capacity = malloc_good_size(amount); buffer.onStack = (pthread_main_np() != 0 ? buffer.capacity < 2048 : buffer.capacity < 512); buffer.memory = buffer.onStack ? alloca(buffer.capacity) : malloc(buffer.capacity); if (buffer.memory == NULL) { return false; } applier(&buffer); if (!buffer.onStack) { free(buffer.memory); } return true; }