blob: 53ef2146c26c37b8711dd0733664813bf3d2ead5 [file] [log] [blame]
//===------------------------------------------------------------*- 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 <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
#import <sys/fcntl.h>
#import <alloca.h>
#import <stdlib.h>
#import <malloc/malloc.h>
#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;
}