bind/objc: fixes miscalculation of string length.
Also, fixes the memory allocation bug - misuse of mem_ensure that caused
to allocate 72 bytes of memory to carry 16 bytes of data for instance.
Fixes golang/go#11842.
Change-Id: I21798be2ec7adfb68cc2897bb46a924f05f3478c
Reviewed-on: https://go-review.googlesource.com/12577
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/bind/objc/SeqTest.m b/bind/objc/SeqTest.m
index 613c2c2..77c5761 100644
--- a/bind/objc/SeqTest.m
+++ b/bind/objc/SeqTest.m
@@ -60,7 +60,8 @@
double y = [s Y];
double sum = [s Sum];
if (x != 10.0 || y != 100.0 || sum != 110.0) {
- ERROR(@"GoTestpkgS(10.0, 100.0).X=%f Y=%f SUM=%f; want 10, 100, 110", x, y, sum);
+ ERROR(@"GoTestpkgS(10.0, 100.0).X=%f Y=%f SUM=%f; want 10, 100, 110", x, y,
+ sum);
}
double sum2 = GoTestpkgCallSSum(s);
@@ -76,6 +77,15 @@
if (x != 7 || y != 70 || sum != 77) {
ERROR(@"GoTestpkgS(7, 70).X=%f Y=%f SUM=%f; want 7, 70, 77", x, y, sum);
}
+
+ NSString *first = @"trytwotested";
+ NSString *second = @"test";
+ NSString *got = [s TryTwoStrings:first second:second];
+ NSString *want = [first stringByAppendingString:second];
+ if (![got isEqualToString:want]) {
+ ERROR(@"GoTestpkgS_TryTwoStrings(%@, %@)= %@; want %@", first, second, got,
+ want);
+ }
}
// Invokes functions and object methods defined in Testpkg.h.
@@ -103,9 +113,12 @@
testBytesAppend(@"Foo", @"Bar");
testStruct();
- int numS = GoTestpkgCollectS(1, 10); // within 10 seconds, collect the S used in testStruct.
+ int numS = GoTestpkgCollectS(
+ 1, 10); // within 10 seconds, collect the S used in testStruct.
if (numS != 1) {
- ERROR(@"%d S objects were collected; S used in testStruct is supposed to be collected.", numS);
+ ERROR(@"%d S objects were collected; S used in testStruct is supposed to "
+ @"be collected.",
+ numS);
}
}
diff --git a/bind/objc/seq_darwin.m b/bind/objc/seq_darwin.m
index a1912bd..bd9cd31 100644
--- a/bind/objc/seq_darwin.m
+++ b/bind/objc/seq_darwin.m
@@ -25,14 +25,24 @@
// mem_ensure ensures that m has at least size bytes free.
// If m is NULL, it is created.
static void mem_ensure(GoSeq *m, uint32_t size) {
- if (m->cap > m->off + size) {
+ size_t cap = m->cap;
+
+ if (cap > m->off + size) {
return;
}
- m->buf = (uint8_t *)realloc((void *)m->buf, m->off + size);
+
+ if (cap == 0) {
+ cap = 64;
+ }
+ while (cap < m->off + size) {
+ cap *= 2;
+ }
+
+ m->buf = (uint8_t *)realloc((void *)m->buf, cap);
if (m->buf == NULL) {
LOG_FATAL(@"mem_ensure realloc failed, off=%zu, size=%u", m->off, size);
}
- m->cap = m->off + size;
+ m->cap = cap;
}
static uint32_t align(uint32_t offset, uint32_t alignment) {
@@ -66,14 +76,7 @@
m->off, m->len, size);
}
uint32_t offset = align(m->off, alignment);
- uint32_t cap = m->cap;
- if (cap == 0) {
- cap = 64;
- }
- while (offset + size > cap) {
- cap *= 2;
- }
- mem_ensure(m, cap);
+ mem_ensure(m, offset - m->off + size);
uint8_t *res = m->buf + offset;
m->off = offset + size;
m->len = offset + size;
@@ -160,7 +163,7 @@
return;
}
- char *buf = (char *)mem_write(seq, len + 1, 1);
+ char *buf = (char *)mem_write(seq, len, 1);
NSUInteger used;
[s getBytes:buf
maxLength:len
diff --git a/bind/objc/testpkg/go_testpkg/go_testpkg.go b/bind/objc/testpkg/go_testpkg/go_testpkg.go
index af6253e..50aae94 100644
--- a/bind/objc/testpkg/go_testpkg/go_testpkg.go
+++ b/bind/objc/testpkg/go_testpkg/go_testpkg.go
@@ -65,12 +65,13 @@
}
const (
- proxyS_Descriptor = "go.testpkg.S"
- proxyS_X_Get_Code = 0x00f
- proxyS_X_Set_Code = 0x01f
- proxyS_Y_Get_Code = 0x10f
- proxyS_Y_Set_Code = 0x11f
- proxyS_Sum_Code = 0x00c
+ proxyS_Descriptor = "go.testpkg.S"
+ proxyS_X_Get_Code = 0x00f
+ proxyS_X_Set_Code = 0x01f
+ proxyS_Y_Get_Code = 0x10f
+ proxyS_Y_Set_Code = 0x11f
+ proxyS_Sum_Code = 0x00c
+ proxyS_TryTwoStrings_Code = 0x10c
)
type proxyS seq.Ref
@@ -106,12 +107,22 @@
out.WriteFloat64(res)
}
+func proxyS_TryTwoStrings(out, in *seq.Buffer) {
+ ref := in.ReadRef()
+ v := ref.Get().(*testpkg.S)
+ param_first := in.ReadString()
+ param_second := in.ReadString()
+ res := v.TryTwoStrings(param_first, param_second)
+ out.WriteString(res)
+}
+
func init() {
seq.Register(proxyS_Descriptor, proxyS_X_Set_Code, proxyS_X_Set)
seq.Register(proxyS_Descriptor, proxyS_X_Get_Code, proxyS_X_Get)
seq.Register(proxyS_Descriptor, proxyS_Y_Set_Code, proxyS_Y_Set)
seq.Register(proxyS_Descriptor, proxyS_Y_Get_Code, proxyS_Y_Get)
seq.Register(proxyS_Descriptor, proxyS_Sum_Code, proxyS_Sum)
+ seq.Register(proxyS_Descriptor, proxyS_TryTwoStrings_Code, proxyS_TryTwoStrings)
}
func proxy_Sum(out, in *seq.Buffer) {
diff --git a/bind/objc/testpkg/objc_testpkg/GoTestpkg.h b/bind/objc/testpkg/objc_testpkg/GoTestpkg.h
index 9307f6d..baf6ab6 100644
--- a/bind/objc/testpkg/objc_testpkg/GoTestpkg.h
+++ b/bind/objc/testpkg/objc_testpkg/GoTestpkg.h
@@ -20,6 +20,7 @@
- (double)Y;
- (void)setY:(double)v;
- (double)Sum;
+- (NSString*)TryTwoStrings:(NSString*)first second:(NSString*)second;
@end
FOUNDATION_EXPORT NSData* GoTestpkgBytesAppend(NSData* a, NSData* b);
diff --git a/bind/objc/testpkg/objc_testpkg/GoTestpkg.m b/bind/objc/testpkg/objc_testpkg/GoTestpkg.m
index 968dd47..a9a47fa 100644
--- a/bind/objc/testpkg/objc_testpkg/GoTestpkg.m
+++ b/bind/objc/testpkg/objc_testpkg/GoTestpkg.m
@@ -9,6 +9,10 @@
static NSString *errDomain = @"go.golang.org/x/mobile/bind/objc/testpkg";
+@protocol goSeqRefInterface
+-(GoSeqRef*) ref;
+@end
+
#define _DESCRIPTOR_ "testpkg"
#define _CALL_BytesAppend_ 1
@@ -27,6 +31,7 @@
#define _GO_testpkg_S_FIELD_Y_GET_ (0x10f)
#define _GO_testpkg_S_FIELD_Y_SET_ (0x11f)
#define _GO_testpkg_S_Sum_ (0x00c)
+#define _GO_testpkg_S_TryTwoStrings_ (0x10c)
@implementation GoTestpkgS {
}
@@ -90,6 +95,19 @@
return ret0_;
}
+- (NSString*)TryTwoStrings:(NSString*)first second:(NSString*)second {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, self.ref);
+ go_seq_writeUTF8(&in_, first);
+ go_seq_writeUTF8(&in_, second);
+ go_seq_send(_GO_testpkg_S_DESCRIPTOR_, _GO_testpkg_S_TryTwoStrings_, &in_, &out_);
+ NSString* ret0_ = go_seq_readUTF8(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
@end
NSData* GoTestpkgBytesAppend(NSData* a, NSData* b) {
@@ -107,7 +125,12 @@
double GoTestpkgCallSSum(GoTestpkgS* s) {
GoSeq in_ = {};
GoSeq out_ = {};
- go_seq_writeRef(&in_, s.ref);
+ if (![s respondsToSelector:@selector(ref)]) {
+ @throw [NSException exceptionWithName:@"InvalidGoSeqRef"
+ reason:@"not a subclass of GoTestpkgSStub"
+ userInfo:nil];
+ }
+ go_seq_writeRef(&in_, [(id<goSeqRefInterface>)s ref]);
go_seq_send(_DESCRIPTOR_, _CALL_CallSSum_, &in_, &out_);
double ret0_ = go_seq_readFloat64(&out_);
go_seq_free(&in_);
diff --git a/bind/objc/testpkg/objc_testpkg/reference/GoTestpkg.h b/bind/objc/testpkg/objc_testpkg/reference/GoTestpkg.h
new file mode 100644
index 0000000..08227f4
--- /dev/null
+++ b/bind/objc/testpkg/objc_testpkg/reference/GoTestpkg.h
@@ -0,0 +1,57 @@
+// Objective-C API for talking to golang.org/x/mobile/bind/objc/testpkg Go package.
+// gobind -lang=objc golang.org/x/mobile/bind/objc/testpkg
+//
+// File is generated by gobind. Do not edit.
+
+#ifndef __GoTestpkg_H__
+#define __GoTestpkg_H__
+
+#include <Foundation/Foundation.h>
+
+@protocol GoTestpkgI
+- (void)Fn:(int32_t)v;
+@end
+
+@interface GoTestpkgI : NSObject {
+}
+@property (strong, readonly) id ref;
+@property (weak, readonly, nonatomic) id delegate;
+
+- (void)call:(int)code in:(void *)in out:(void *)out;
+@end
+
+@class GoTestpkgS;
+
+@interface GoTestpkgS : NSObject {
+}
+@property(strong, readonly) id ref;
+
+- (id)initWithRef:(id)ref;
+- (double)X;
+- (void)setX:(double)v;
+- (double)Y;
+- (void)setY:(double)v;
+- (double)Sum;
+@end
+
+FOUNDATION_EXPORT NSData* GoTestpkgBytesAppend(NSData* a, NSData* b);
+
+FOUNDATION_EXPORT void GoTestpkgCallI(GoTestpkgI* i, int32_t v);
+
+FOUNDATION_EXPORT double GoTestpkgCallSSum(GoTestpkgS* s);
+
+FOUNDATION_EXPORT int GoTestpkgCollectS(int want, int timeoutSec);
+
+FOUNDATION_EXPORT NSString* GoTestpkgHello(NSString* s);
+
+FOUNDATION_EXPORT void GoTestpkgHi();
+
+FOUNDATION_EXPORT void GoTestpkgInt(int32_t x);
+
+FOUNDATION_EXPORT GoTestpkgS* GoTestpkgNewS(double x, double y);
+
+FOUNDATION_EXPORT BOOL GoTestpkgReturnsError(BOOL b, NSString** ret0_, NSError** error);
+
+FOUNDATION_EXPORT int64_t GoTestpkgSum(int64_t x, int64_t y);
+
+#endif
diff --git a/bind/objc/testpkg/objc_testpkg/reference/GoTestpkg.m b/bind/objc/testpkg/objc_testpkg/reference/GoTestpkg.m
new file mode 100644
index 0000000..dedf816
--- /dev/null
+++ b/bind/objc/testpkg/objc_testpkg/reference/GoTestpkg.m
@@ -0,0 +1,249 @@
+// Objective-C API for talking to golang.org/x/mobile/bind/objc/testpkg Go package.
+// gobind -lang=objc golang.org/x/mobile/bind/objc/testpkg
+//
+// File is generated by gobind. Do not edit.
+
+#include "GoTestpkg.h"
+#include <Foundation/Foundation.h>
+#include "seq.h"
+
+static NSString *errDomain = @"go.golang.org/x/mobile/bind/objc/testpkg";
+
+#define _DESCRIPTOR_ "testpkg"
+
+#define _CALL_BytesAppend_ 1
+#define _CALL_CallI_ 2
+#define _CALL_CallSSum_ 3
+#define _CALL_CollectS_ 4
+#define _CALL_Hello_ 5
+#define _CALL_Hi_ 6
+#define _CALL_Int_ 7
+#define _CALL_NewS_ 8
+#define _CALL_ReturnsError_ 9
+#define _CALL_Sum_ 10
+
+#define _GO_testpkg_S_DESCRIPTOR_ "go.testpkg.S"
+#define _GO_testpkg_S_FIELD_X_GET_ (0x00f)
+#define _GO_testpkg_S_FIELD_X_SET_ (0x01f)
+#define _GO_testpkg_S_FIELD_Y_GET_ (0x10f)
+#define _GO_testpkg_S_FIELD_Y_SET_ (0x11f)
+#define _GO_testpkg_S_Sum_ (0x00c)
+
+#define _GO_testpkg_I_DESCRIPTOR_ "go.testpkg.I"
+#define _GO_testpkg_I_Fn_ 0x10a
+
+@implementation GoTestpkgI {
+}
+@synthesize delegate = _delegate;
+@synthesize ref = _ref;
+
+- (id)init {
+ self = [super init];
+ if (self) {
+ _delegate = self;
+ _ref = [GoSeqRef newForObject:self];
+ }
+ return self;
+}
+
+- (void)call:(int)code in:(void *)in out:(void *)out {
+ GoSeq* inseq = (GoSeq*)in;
+ GoSeq* outseq = (GoSeq*)out;
+ switch (code) {
+ case _GO_testpkg_I_Fn_:
+ {
+ int32_t v = go_seq_readInt32(inseq);
+ [_delegate Fn:v];
+ return;
+ }
+ default:
+ NSLog(@"unknown code %s:%d", _GO_testpkg_I_DESCRIPTOR_, code);
+ }
+}
+
+@end
+
+@implementation GoTestpkgS {
+}
+
+- (id)initWithRef:(id)ref {
+ self = [super init];
+ if (self) { _ref = ref; }
+ return self;
+}
+
+- (double)X {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, self.ref);
+ go_seq_send(_GO_testpkg_S_DESCRIPTOR_, _GO_testpkg_S_FIELD_X_GET_, &in_, &out_);
+ double ret_ = go_seq_readFloat64(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret_;
+}
+
+- (void)setX:(double)v {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, self.ref);
+ go_seq_writeFloat64(&in_, v);
+ go_seq_send(_GO_testpkg_S_DESCRIPTOR_, _GO_testpkg_S_FIELD_X_SET_, &in_, &out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+}
+
+- (double)Y {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, self.ref);
+ go_seq_send(_GO_testpkg_S_DESCRIPTOR_, _GO_testpkg_S_FIELD_Y_GET_, &in_, &out_);
+ double ret_ = go_seq_readFloat64(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret_;
+}
+
+- (void)setY:(double)v {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, self.ref);
+ go_seq_writeFloat64(&in_, v);
+ go_seq_send(_GO_testpkg_S_DESCRIPTOR_, _GO_testpkg_S_FIELD_Y_SET_, &in_, &out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+}
+
+- (double)Sum {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, self.ref);
+ go_seq_send(_GO_testpkg_S_DESCRIPTOR_, _GO_testpkg_S_Sum_, &in_, &out_);
+ double ret0_ = go_seq_readFloat64(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
+@end
+
+NSData* GoTestpkgBytesAppend(NSData* a, NSData* b) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeByteArray(&in_, a);
+ go_seq_writeByteArray(&in_, b);
+ go_seq_send(_DESCRIPTOR_, _CALL_BytesAppend_, &in_, &out_);
+ NSData* ret0_ = go_seq_readByteArray(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
+void GoTestpkgCallI(GoTestpkgI* i, int32_t v) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, i.ref);
+ go_seq_writeInt32(&in_, v);
+ go_seq_send(_DESCRIPTOR_, _CALL_CallI_, &in_, &out_);
+ return;
+}
+
+double GoTestpkgCallSSum(GoTestpkgS* s) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeRef(&in_, s.ref);
+ go_seq_send(_DESCRIPTOR_, _CALL_CallSSum_, &in_, &out_);
+ double ret0_ = go_seq_readFloat64(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
+int GoTestpkgCollectS(int want, int timeoutSec) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeInt(&in_, want);
+ go_seq_writeInt(&in_, timeoutSec);
+ go_seq_send(_DESCRIPTOR_, _CALL_CollectS_, &in_, &out_);
+ int ret0_ = go_seq_readInt(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
+NSString* GoTestpkgHello(NSString* s) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeUTF8(&in_, s);
+ go_seq_send(_DESCRIPTOR_, _CALL_Hello_, &in_, &out_);
+ NSString* ret0_ = go_seq_readUTF8(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
+void GoTestpkgHi() {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_send(_DESCRIPTOR_, _CALL_Hi_, &in_, &out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+}
+
+void GoTestpkgInt(int32_t x) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeInt32(&in_, x);
+ go_seq_send(_DESCRIPTOR_, _CALL_Int_, &in_, &out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+}
+
+GoTestpkgS* GoTestpkgNewS(double x, double y) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeFloat64(&in_, x);
+ go_seq_writeFloat64(&in_, y);
+ go_seq_send(_DESCRIPTOR_, _CALL_NewS_, &in_, &out_);
+ GoSeqRef* ret0__ref = go_seq_readRef(&out_);
+ GoTestpkgS* ret0_ = ret0__ref.obj;
+ if (ret0_ == NULL) {
+ ret0_ = [[GoTestpkgS alloc] initWithRef:ret0__ref];
+ }
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
+BOOL GoTestpkgReturnsError(BOOL b, NSString** ret0_, NSError** error) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeBool(&in_, b);
+ go_seq_send(_DESCRIPTOR_, _CALL_ReturnsError_, &in_, &out_);
+ NSString* ret0__val = go_seq_readUTF8(&out_);
+ if (ret0_ != NULL) {
+ *ret0_ = ret0__val;
+ }
+ NSString* _error = go_seq_readUTF8(&out_);
+ if ([_error length] != 0 && error != nil) {
+ NSMutableDictionary *details = [NSMutableDictionary dictionary];
+ [details setValue:_error forKey:NSLocalizedDescriptionKey];
+ *error = [NSError errorWithDomain:errDomain code:1 userInfo:details];
+ }
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ([_error length] == 0);
+}
+
+int64_t GoTestpkgSum(int64_t x, int64_t y) {
+ GoSeq in_ = {};
+ GoSeq out_ = {};
+ go_seq_writeInt64(&in_, x);
+ go_seq_writeInt64(&in_, y);
+ go_seq_send(_DESCRIPTOR_, _CALL_Sum_, &in_, &out_);
+ int64_t ret0_ = go_seq_readInt64(&out_);
+ go_seq_free(&in_);
+ go_seq_free(&out_);
+ return ret0_;
+}
+
diff --git a/bind/objc/testpkg/testpkg.go b/bind/objc/testpkg/testpkg.go
index e0895dd..955854c 100644
--- a/bind/objc/testpkg/testpkg.go
+++ b/bind/objc/testpkg/testpkg.go
@@ -75,6 +75,10 @@
return s
}
+func (s *S) TryTwoStrings(first, second string) string {
+ return first + second
+}
+
func (s *S) Sum() float64 {
return s.X + s.Y
}