1/* 2 * 3 * Copyright 2018 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19#import "ChannelArgsUtil.h" 20 21#include <grpc/support/alloc.h> 22#include <grpc/support/string_util.h> 23 24#include <limits.h> 25 26static void *copy_pointer_arg(void *p) { 27 // Add ref count to the object when making copy 28 id obj = (__bridge id)p; 29 return (__bridge_retained void *)obj; 30} 31 32static void destroy_pointer_arg(void *p) { 33 // Decrease ref count to the object when destroying 34 CFRelease((CFTypeRef)p); 35} 36 37static int cmp_pointer_arg(void *p, void *q) { return p == q; } 38 39static const grpc_arg_pointer_vtable objc_arg_vtable = {copy_pointer_arg, destroy_pointer_arg, 40 cmp_pointer_arg}; 41 42void GRPCFreeChannelArgs(grpc_channel_args *channel_args) { 43 for (size_t i = 0; i < channel_args->num_args; ++i) { 44 grpc_arg *arg = &channel_args->args[i]; 45 gpr_free(arg->key); 46 if (arg->type == GRPC_ARG_STRING) { 47 gpr_free(arg->value.string); 48 } 49 } 50 gpr_free(channel_args->args); 51 gpr_free(channel_args); 52} 53 54grpc_channel_args *GRPCBuildChannelArgs(NSDictionary *dictionary) { 55 if (dictionary.count == 0) { 56 return NULL; 57 } 58 59 NSArray *keys = [dictionary allKeys]; 60 NSUInteger argCount = [keys count]; 61 62 grpc_channel_args *channelArgs = (grpc_channel_args *)gpr_malloc(sizeof(grpc_channel_args)); 63 channelArgs->args = (grpc_arg *)gpr_malloc(argCount * sizeof(grpc_arg)); 64 65 // TODO(kriswuollett) Check that keys adhere to GRPC core library requirements 66 67 NSUInteger j = 0; 68 for (NSUInteger i = 0; i < argCount; ++i) { 69 grpc_arg *arg = &channelArgs->args[j]; 70 arg->key = gpr_strdup([keys[i] UTF8String]); 71 72 id value = dictionary[keys[i]]; 73 if ([value respondsToSelector:@selector(UTF8String)]) { 74 arg->type = GRPC_ARG_STRING; 75 arg->value.string = gpr_strdup([value UTF8String]); 76 j++; 77 } else if ([value respondsToSelector:@selector(intValue)]) { 78 int64_t value64 = [value longLongValue]; 79 if (value64 <= INT_MAX || value64 >= INT_MIN) { 80 arg->type = GRPC_ARG_INTEGER; 81 arg->value.integer = (int)value64; 82 j++; 83 } 84 } else if (value != nil) { 85 arg->type = GRPC_ARG_POINTER; 86 arg->value.pointer.p = (__bridge_retained void *)value; 87 arg->value.pointer.vtable = &objc_arg_vtable; 88 j++; 89 } 90 } 91 channelArgs->num_args = j; 92 93 return channelArgs; 94} 95