Skip to content

Commit

Permalink
fixed build error on 32bit systems with pointer-to-slice casts
Browse files Browse the repository at this point in the history
As part of this, these casts were centralized, with an explanation what to do. The compiler most likely inlines them again, anyway.
  • Loading branch information
dertseha committed Jun 14, 2020
1 parent b81cdba commit ff6b2a6
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 8 deletions.
2 changes: 1 addition & 1 deletion AllocatedGlyphRanges.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (builder *GlyphRangesBuilder) Build() AllocatedGlyphRanges {
const uint16PerRangeEntry = 2
ranges := builder.mergedRanges()
raw := C.malloc(C.size_t(bytesPerUint16 * ((len(ranges) * uint16PerRangeEntry) + 1)))
rawSlice := (*[1 << 30]uint16)(raw)[:]
rawSlice := ptrToUint16Slice(raw)
outIndex := 0
for _, r := range ranges {
rawSlice[outIndex+0] = r.from
Expand Down
2 changes: 1 addition & 1 deletion FontAtlas.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (atlas FontAtlas) AddFontFromMemoryTTFV(
}

fontDataC := C.malloc(C.size_t(len(fontData)))
cBuf := (*[1 << 30]byte)(fontDataC)
cBuf := ptrToByteSlice(fontDataC)

copy(cBuf[:], fontData)

Expand Down
2 changes: 1 addition & 1 deletion GlyphRanges.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (glyphs GlyphRanges) extract() (result []glyphRange) {
if glyphs == 0 {
return
}
rawSlice := (*[1 << 30]uint16)(unsafe.Pointer(glyphs.handle()))[:]
rawSlice := ptrToUint16Slice(unsafe.Pointer(glyphs.handle()))
index := 0
// iterate until end of list or an arbitrary paranoia limit, should the list not be proper.
for (rawSlice[index] != 0) && (index < 1000) {
Expand Down
2 changes: 1 addition & 1 deletion InputTextCallbackData.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (data InputTextCallbackData) Buffer() []byte {
return nil
}
textLen := data.bufTextLen()
return ((*[1 << 30]byte)(unsafe.Pointer(ptr)))[:textLen]
return ptrToByteSlice(unsafe.Pointer(ptr))[:textLen]
}

// MarkBufferModified indicates that the content of the buffer was modified during a callback.
Expand Down
24 changes: 20 additions & 4 deletions WrapperConverter.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ func newStringBuffer(initialValue string) *stringBuffer {
bufSize := len(rawText) + 1
newPtr := C.malloc(C.size_t(bufSize))
zeroOffset := bufSize - 1
copy(((*[1 << 30]byte)(newPtr))[:zeroOffset], rawText)
((*[1 << 30]byte)(newPtr))[zeroOffset] = 0
buf := ptrToByteSlice(newPtr)
copy(buf[:zeroOffset], rawText)
buf[zeroOffset] = 0

return &stringBuffer{ptr: newPtr, size: bufSize}
}
Expand All @@ -101,7 +102,7 @@ func (buf *stringBuffer) resizeTo(requestedSize int) {
if copySize > 0 {
C.memcpy(newPtr, buf.ptr, C.size_t(copySize))
}
((*[1 << 30]byte)(newPtr))[bufSize-1] = 0
ptrToByteSlice(newPtr)[bufSize-1] = 0
C.free(buf.ptr)
buf.ptr = newPtr
buf.size = bufSize
Expand All @@ -111,6 +112,21 @@ func (buf stringBuffer) toGo() string {
if (buf.ptr == nil) || (buf.size < 1) {
return ""
}
((*[1 << 30]byte)(buf.ptr))[buf.size-1] = 0
ptrToByteSlice(buf.ptr)[buf.size-1] = 0
return C.GoString((*C.char)(buf.ptr))
}

// unrealisticLargePointer is used to cast an arbitrary native pointer to a slice.
// Its value is chosen to fit into a 32bit architecture, and still be large
// enough to cover "any" data blob. Note that this value is in bytes.
// Should an array of larger primitives be addressed, be sure to divide the value
// by the size of the elements.
const unrealisticLargePointer = 1 << 30

func ptrToByteSlice(p unsafe.Pointer) []byte {
return (*[unrealisticLargePointer]byte)(p)[:]
}

func ptrToUint16Slice(p unsafe.Pointer) []uint16 {
return (*[unrealisticLargePointer / 2]uint16)(p)[:]
}

0 comments on commit ff6b2a6

Please sign in to comment.