github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/ext/zorder/zorder.go (about)

     1  // Package zorder provides functions for z-order transformations.
     2  //
     3  // https://sqlite.org/src/doc/tip/ext/misc/zorder.c
     4  package zorder
     5  
     6  import (
     7  	"github.com/ncruces/go-sqlite3"
     8  	"github.com/ncruces/go-sqlite3/internal/util"
     9  )
    10  
    11  // Register registers the zorder and unzorder SQL functions.
    12  func Register(db *sqlite3.Conn) {
    13  	flags := sqlite3.DETERMINISTIC | sqlite3.INNOCUOUS
    14  	db.CreateFunction("zorder", -1, flags, zorder)
    15  	db.CreateFunction("unzorder", 3, flags, unzorder)
    16  }
    17  
    18  func zorder(ctx sqlite3.Context, arg ...sqlite3.Value) {
    19  	var x [63]int64
    20  	for i := range arg {
    21  		x[i] = arg[i].Int64()
    22  	}
    23  	if len(arg) > len(x) {
    24  		ctx.ResultError(util.ErrorString("zorder: too many parameters"))
    25  		return
    26  	}
    27  
    28  	var z int64
    29  	if len(arg) > 0 {
    30  		for i := 0; i < 63; i++ {
    31  			j := i % len(arg)
    32  			z |= (x[j] & 1) << i
    33  			x[j] >>= 1
    34  		}
    35  	}
    36  
    37  	for i := range arg {
    38  		if x[i] != 0 {
    39  			ctx.ResultError(util.ErrorString("zorder: parameter too large"))
    40  			return
    41  		}
    42  	}
    43  	ctx.ResultInt64(z)
    44  }
    45  
    46  func unzorder(ctx sqlite3.Context, arg ...sqlite3.Value) {
    47  	z := arg[0].Int64()
    48  	n := arg[1].Int64()
    49  	i := arg[2].Int64()
    50  
    51  	var k int
    52  	var x int64
    53  	for j := i; j < 63; j += n {
    54  		x |= ((z >> j) & 1) << k
    55  		k++
    56  	}
    57  	ctx.ResultInt64(x)
    58  }