commit b6d598696ceac3ea57864a0ab5445ac9c2b7e228 Author: Greg Date: Wed Jan 9 18:21:20 2019 -0500 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3b4c521 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ + +cmd/rand/rand +cmd/rand-gui/rand-gui +cmd/rand-gui/.gradle +cmd/rand-gui/gradle/ +cmd/rand-gui/gradlew +cmd/rand-gui/gradlew.bat +cmd/rand-gui/build/ +cmd/rand-gui/android/build/ +cmd/rand-gui/android/build_go/ +cmd/rand-gui/android/src/main/jniLibs/ +cmd/rand-gui/bindata.go diff --git a/cmd/rand-gui/Makefile b/cmd/rand-gui/Makefile new file mode 100644 index 0000000..195c91a --- /dev/null +++ b/cmd/rand-gui/Makefile @@ -0,0 +1,22 @@ + +darwin: bindata.go + go generate + go build + +gradlew: + gradle wrapper + +android: gradlew bindata.go + go generate + ./gradlew build + +android-install: gradlew bindata.go + go generate + ./gradlew installDebug + +bindata.go: assets/DroidSans.ttf + go-bindata assets/DroidSans.ttf + +clean: + rm -rf bindata.go android/build android/build_go android/src/main/jniLibs build gradlew gradlew.bat .gradle gradle commute + diff --git a/cmd/rand-gui/alog b/cmd/rand-gui/alog new file mode 100755 index 0000000..c9bf49d --- /dev/null +++ b/cmd/rand-gui/alog @@ -0,0 +1,4 @@ +#!/bin/bash + +adb logcat Rand *:S > alogs + diff --git a/cmd/rand-gui/android.go b/cmd/rand-gui/android.go new file mode 100644 index 0000000..fa6af58 --- /dev/null +++ b/cmd/rand-gui/android.go @@ -0,0 +1,201 @@ +//+build !darwin + +package main + +import ( + "time" + + "github.com/xlab/android-go/android" + "github.com/xlab/android-go/app" + gl "github.com/xlab/android-go/gles31" + + //"github.com/golang-ui/nuklear/nk" + "gitlab.wow.st/gmp/nuklear/nk" +) + +const ( + datadir = "/storage/emulated/0/Android/data/st.wow.gitlab.gmp.commute/" + fontSize = 64 +) + +func platformInit() { + gl.Enable(gl.CULL_FACE) + gl.Disable(gl.DEPTH_TEST) + app.SetLogTag("Commute") +} + +func mkWin() { +} + +func Terminate() { + return +} + +func PollEvents() { + return +} + +func GetSize() (width, height int) { + handle := nk.NkPlatformDisplayHandle() + return handle.Width, handle.Height +} + +func SwapBuffers() { +} + +var ( + nativeWindowEvents chan app.NativeWindowEvent + inputQueueEvents chan app.InputQueueEvent + inputQueueChan chan *android.InputQueue + backPressed bool +) + +func eventloop() { + nativeWindowEvents = make(chan app.NativeWindowEvent, 1) + inputQueueEvents = make(chan app.InputQueueEvent, 1) + inputQueueChan = make(chan *android.InputQueue, 1) + + app.Main(appmain) + log(Info,"app.Main returned") +} + +func appmain(a app.NativeActivity) { + log(Info,"appmain() start") + fpsTicker := time.NewTicker(frametime) + a.HandleNativeWindowEvents(nativeWindowEvents) + a.HandleInputQueueEvents(inputQueueEvents) + log(Info,"appmain() launching init thread") + inputs := make(chan struct{},64) + go app.HandleInputQueues(inputQueueChan, func() { + a.InputQueueHandled() + }, func(ev *android.InputEvent) { + switch android.InputEventGetType(ev) { + case android.InputEventTypeKey: + key := android.KeyEventGetKeyCode(ev) + action := android.KeyEventGetAction(ev) + meta := android.KeyEventGetMetaState(ev) + switch action { + case android.KeyEventActionDown: + if key == android.KeycodeBack { + backPressed = true + inputs<- struct{}{} + return + } + fallthrough + case android.KeyEventActionUp: + nk.NkPlatformInput(nil, &nk.PlatformKeyEvent{ + Activity: a.NativeActivity(), + Action: action, + KeyCode: key, + MetaState: meta, + }) + inputs<- struct{}{} + } + case android.InputEventTypeMotion: + action := android.MotionEventGetAction(ev) + switch action { + case android.MotionEventActionDown, + android.MotionEventActionMove, + android.MotionEventActionUp: + x := android.MotionEventGetX(ev, 0) + y := android.MotionEventGetY(ev, 0) + nk.NkPlatformInput(&nk.PlatformTouchEvent{ + Action: action, + X: int32(x), + Y: int32(y), + }, nil) + inputs<- struct{}{} + } + } + }) + a.InitDone() + log(Info,"appmain() starting event loop") + for { + select { + case event := <-a.LifecycleEvents(): + log(Info,"appmain(): lifecycle ", event) + case event := <-inputQueueEvents: + log(Debug,"appmain(): inputQueueEvent ", event) + switch event.Kind { + case app.QueueCreated: + inputQueueChan <- event.Queue + case app.QueueDestroyed: + inputQueueChan <- nil + } + if ctx != nil { + gfxMain() + } + case <-fpsTicker.C: + log(DebugGfx,"appmain(): fpsTicker") + if ctx != nil { + log(DebugGfx,"gfxMain()") + fpsTicker.Stop() + gfxMain() + fpsTicker = newTicker() + } + case <-inputs: + log(Debug,"appmain(): inputs queue") + if ctx != nil { + fpsTicker.Stop() + gfxMain() + fpsTicker = newFastTicker() + } + case event := <-nativeWindowEvents: + log(Info,"appmain(): nativeWindowEvents", event) + switch event.Kind { + case app.NativeWindowRedrawNeeded: + log(Info,"appmain(): redraw") + fpsTicker.Stop() + gfxMain() + a.NativeWindowRedrawDone() + fpsTicker = newTicker() + case app.NativeWindowCreated: + log(Info,"appmain(): window created") + ctx = nk.NkPlatformInit(event.Window, nk.PlatformInstallCallbacks) + log(Info,"appmain(): init returned") + if ctx == nil { + log(Fatal,"Nuklear failed to init") + } + loadFont() + fpsTicker = newTicker() + log(Info,"appmain(): done with create window") + case app.NativeWindowDestroyed: + log(Info,"appmain(): window destroyed") + //refresh = true + fpsTicker.Stop() + nk.NkPlatformShutdown() + Drain: + for { + select { + case <-inputs: + default: + break Drain + } + } + } + } + backPressed = false + } + log(Info,"appmain: returning") +} + +func newFastTicker() *time.Ticker { + return time.NewTicker(time.Second / 60) +} + +func newTicker() *time.Ticker { + if y != lastY { + return time.NewTicker(time.Second / 60) + } else { + return time.NewTicker(time.Second) + } +} + +func BackButton(string) bool { + return backPressed +} + +func Clip(x string) { + +} + diff --git a/cmd/rand-gui/android/build.gradle b/cmd/rand-gui/android/build.gradle new file mode 100644 index 0000000..44a4c72 --- /dev/null +++ b/cmd/rand-gui/android/build.gradle @@ -0,0 +1,40 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion = rootProject.ext.sdkVersion + + defaultConfig { + ndk { + abiFilters rootProject.ext.archs.split(",") + } + } + buildTypes { + release + debug { + jniDebuggable true + } + } +} + +task buildGo(type: Exec) { + commandLine '../bash_script/build_go.sh', rootProject.ext.archs, rootProject.ext.sdkVersion +} + +task prepareToolchain(type: Exec) { + commandLine '../bash_script/build_toolchain.sh', rootProject.ext.archs, rootProject.ext.sdkVersion +} + +task cleanToolchain(type: Exec) { + commandLine 'rm', '-r', 'build_go/toolchain' +} + +task cleanOutput(type: Exec) { + commandLine 'rm', '-r', 'build_go/output' +} + + +afterEvaluate { + buildGo.dependsOn prepareToolchain + preBuild.dependsOn buildGo + clean.dependsOn cleanOutput +} \ No newline at end of file diff --git a/cmd/rand-gui/android/src/main/AndroidManifest.xml b/cmd/rand-gui/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c59b1a0 --- /dev/null +++ b/cmd/rand-gui/android/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/cmd/rand-gui/assets/DroidSans.ttf b/cmd/rand-gui/assets/DroidSans.ttf new file mode 100644 index 0000000..767c63a Binary files /dev/null and b/cmd/rand-gui/assets/DroidSans.ttf differ diff --git a/cmd/rand-gui/bash_script/build_go.sh b/cmd/rand-gui/bash_script/build_go.sh new file mode 100755 index 0000000..65e3325 --- /dev/null +++ b/cmd/rand-gui/bash_script/build_go.sh @@ -0,0 +1,60 @@ +#!/bin/bash +#Working directory is /android +set -e + +if ! [ -d "$ANDROID_HOME" ]; +then +printf "ANDROID_HOME does not point to any directory. Please set ANDROID_HOME variable\n" +exit 1 +fi + +ABIS=($(echo $1 | sed 's/,/ /g')) +ANDROID_API=$2 +printf "Build Go sources using ABIs: %s Android API: %s\n" "${ABIS[*]}" "$ANDROID_API" + +TOOLCHAIN_ROOT_DIR=build_go/toolchain +OUTPUT_ROOT_DIR=build_go/output +printf "Cleaning output dir %s\n" "$OUTPUT_ROOT_DIR" +rm -rf "$OUTPUT_ROOT_DIR" + +for ABI in ${ABIS[*]} +do +GOARCH= +GOARM= +CC= +CXX= +CGO_CFLAGS= + +case $ABI in +armeabi-v7a) +GOARCH="arm" +GOARM=7 +CC="$TOOLCHAIN_ROOT_DIR/arm/bin/arm-linux-androideabi-gcc" +CXX="$TOOLCHAIN_ROOT_DIR/arm/bin/arm-linux-androideabi-g++" +CGO_CFLAGS="-march=armv7-a" +;; +x86) +GOARCH="386" +GOARM= +CC="$TOOLCHAIN_ROOT_DIR/x86/bin/i686-linux-android-gcc" +CXX="$TOOLCHAIN_ROOT_DIR/x86/bin/i686-linux-android-g++" +CGO_CFLAGS= +;; +*) +continue +;; +esac + + +OUTPUT_DIR="$OUTPUT_ROOT_DIR/$ABI" +mkdir -p "$OUTPUT_DIR" + +cd .. +set -x +CURRENT_DIR=$(pwd) +CC="$CURRENT_DIR/android/$CC" CXX="$CURRENT_DIR/android/$CXX" CGO_ENABLED=1 \ +CGO_CFLAGS="$CGO_CFLAGS" GOOS=android GOARCH="$GOARCH" GOARM="$GOARM" \ +go build -i -pkgdir "$CURRENT_DIR/android/$OUTPUT_DIR" -buildmode=c-shared -o "android/src/main/jniLibs/$ABI/libgomain.so" +cd android +set +x +done \ No newline at end of file diff --git a/cmd/rand-gui/bash_script/build_toolchain.sh b/cmd/rand-gui/bash_script/build_toolchain.sh new file mode 100755 index 0000000..cc0c044 --- /dev/null +++ b/cmd/rand-gui/bash_script/build_toolchain.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +#Working directory is /android +set -e + +if ! [ -d "$ANDROID_HOME" ]; +then +printf "ANDROID_HOME does not point to any directory. Please set ANDROID_HOME variable\n" +exit 1 +fi + +ABIS=($(echo $1 | sed 's/,/ /g')) +ANDROID_API=$2 +printf "Preparing toolchains for ABIs: %s Android API: %s\n" "${ABIS[*]}" $ANDROID_API + + +TOOLCHAIN_ROOT_DIR=build_go/toolchain + +declare -A ARCHS +for ABI in ${ABIS[*]} +do +case $ABI in +armeabi-v7a) +ARCH="arm" +;; +x86) +ARCH="x86" +;; +*) +continue +;; +esac + +ARCHS[$ARCH]=1 +done + +for ARCH in ${!ARCHS[*]} +do +TOOLCHAIN_DIR="$TOOLCHAIN_ROOT_DIR/$ARCH" + +if [ -d "$TOOLCHAIN_DIR" ]; +then +printf "Using existing standalone toolchain for arch: %s\n" $ARCH +continue +fi + +printf "Making standalone toolchain for arch: %s\n" $ARCH +set -x +"$ANDROID_HOME"/ndk-bundle/build/tools/make_standalone_toolchain.py \ + --api=$ANDROID_API --install-dir=$TOOLCHAIN_DIR \ + --arch=$ARCH --stl libc++ +set +x +printf "Standalone toolchain ready\n" +done diff --git a/cmd/rand-gui/build.gradle b/cmd/rand-gui/build.gradle new file mode 100644 index 0000000..ee595f5 --- /dev/null +++ b/cmd/rand-gui/build.gradle @@ -0,0 +1,13 @@ +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.0' + } + ext { + archs = "armeabi-v7a,x86" + sdkVersion = 26 + } +} diff --git a/cmd/rand-gui/darwin.go b/cmd/rand-gui/darwin.go new file mode 100644 index 0000000..77a9476 --- /dev/null +++ b/cmd/rand-gui/darwin.go @@ -0,0 +1,102 @@ +//+build !android + +package main + +import ( + "bytes" + "os/exec" + "time" + + "github.com/go-gl/gl/v3.2-core/gl" + "github.com/go-gl/glfw/v3.2/glfw" + //"github.com/golang-ui/nuklear/nk" + "gitlab.wow.st/gmp/nuklear/nk" +) + +var ( + win *glfw.Window +) + +const ( + datadir = "./" + fontSize = 24 +) + +func platformInit() { + return +} + +func mkWin() { + var err error + if err = glfw.Init(); err != nil { + log(Fatal, err) + } + glfw.WindowHint(glfw.ContextVersionMajor, 3) + glfw.WindowHint(glfw.ContextVersionMinor, 2) + glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) + glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) + win, err = glfw.CreateWindow(initWidth, initHeight, "Commute", nil, nil) + if err != nil { + log(Fatal, err) + } + win.MakeContextCurrent() + + width, height := win.GetSize() + log(Info, "created window ", width, "x", height) + + if err := gl.Init(); err != nil { + log(Fatal,"opengl: init failed: ", err) + } + gl.Viewport(0,0, int32(width), int32(height)) + + ctx = nk.NkPlatformInit(win, nk.PlatformInstallCallbacks) + + loadFont() +} + +func Terminate() { + glfw.Terminate() +} + +func PollEvents() { + glfw.PollEvents() +} + +func GetSize() (width, height int) { + return win.GetSize() +} + +func SwapBuffers() { + win.SwapBuffers() +} + +func eventloop() { + for { +// if nk.Animate() && lastY != y { + if lastY != y { + glfw.WaitEventsTimeout(float64(1/60)) + } else { + time.Sleep(time.Second/60) + glfw.WaitEventsTimeout(float64(1)) + } + gfxMain() + glfw.WaitEventsTimeout(float64(1/60)) + gfxMain() + if win.ShouldClose() { + break + } + } +} + +func BackButton(s string) bool { + return button(s) +} + + +func Clip(x string) { + b := bytes.NewBuffer([]byte(x)) + cmd := exec.Command("pbcopy") + cmd.Stdin = b + cmd.Run() +} + diff --git a/cmd/rand-gui/log.go b/cmd/rand-gui/log.go new file mode 100644 index 0000000..83d8756 --- /dev/null +++ b/cmd/rand-gui/log.go @@ -0,0 +1,28 @@ +package main + +import ( + golog "log" + "os" +) + +type logLevelT int +const ( + Fatal logLevelT = 1 << iota + Error + Warn + Info + Debug + DebugGfx +) + +var loglevel = Fatal | Error | Warn | Info + +func log(level logLevelT, msg ...interface{}) { + if level & loglevel != 0 { + golog.Print(msg...) + } + if level & Fatal != 0 { + os.Exit(-1) + } +} + diff --git a/cmd/rand-gui/main.go b/cmd/rand-gui/main.go new file mode 100644 index 0000000..a3f2339 --- /dev/null +++ b/cmd/rand-gui/main.go @@ -0,0 +1,121 @@ +// +build darwin linux + +package main + +import ( + "fmt" + "runtime" + "strconv" + + "gitlab.wow.st/gmp/rand" + //"gitlab.wow.st/gmp/nuklear/nk" +) + +func main() { + runtime.LockOSThread() + + length = 5 + buf = make([]byte,16) + copy(buf,[]byte(fmt.Sprintf("%d\000",length))) + fmt.Println(buf) + fun = rand.Char + + generate() + log(Info,"Staring event loop") + uiInit() + eventloop() + log(Info,"Event loop returned") +} + +const ( + maxlen int = 40 +) + +var ( + fun func() (byte,error) + length int + out []byte + buf []byte +) + +func generate() { + if length <= 0 { + return + } + buf, err := rand.Slice(fun,length) + if err != nil { + out = []byte("Error") + } + out = buf +} + +func gfxMain() { + if ctx == nil { + log(Error,"gfxMain(): ctx is nil") + return + } + + if uiBegin() { + row(4) + if button("Char") { + fun = rand.Char + generate() + } + if button("Letter") { + fun = rand.Letter + generate() + } + if button("Digit") { + fun = rand.Digit + generate() + } + if button("Symbol") { + fun = rand.Symbol + generate() + } + row(3) + if button("<") { + length -= 1; + if length == 0 { + length = 1 + } + copy(buf,[]byte(fmt.Sprintf("%d\000",length))) + generate() + } + //label(fmt.Sprintf("%d",length),nk.TextAlignCentered | nk.TextAlignMiddle) + editstring(buf) + lastlen := length + nb := make([]byte,0) + for i := 0; i < len(buf); i++ { + if buf[i] == 0 || buf[i] == '\n' { + break + } + nb = append(nb,buf[i]) + } + num,err := strconv.Atoi(string(nb)) + if err == nil { + length = num + } + if length != lastlen { + if length > maxlen { + length = maxlen + } + copy(buf,[]byte(fmt.Sprintf("%d\000",length))) + generate() + } + if button(">") { + length += 1; + if length > maxlen { + length = maxlen + } + copy(buf,[]byte(fmt.Sprintf("%d\000",length))) + generate() + } + row(1) + if button(string(out)) { + Clip(string(out)) + } + } + uiEnd() +} + diff --git a/cmd/rand-gui/settings.gradle b/cmd/rand-gui/settings.gradle new file mode 100644 index 0000000..0268643 --- /dev/null +++ b/cmd/rand-gui/settings.gradle @@ -0,0 +1 @@ +include ':android' \ No newline at end of file diff --git a/cmd/rand-gui/ui.go b/cmd/rand-gui/ui.go new file mode 100644 index 0000000..fb7d8a1 --- /dev/null +++ b/cmd/rand-gui/ui.go @@ -0,0 +1,132 @@ +package main + +// helper functions for UI + +import ( + "time" + + //"github.com/golang-ui/nuklear/nk" + "gitlab.wow.st/gmp/nuklear/nk" +) + +const ( + initWidth = 600 + initHeight = 400 + + maxVertexBuffer = 512 * 1024 + maxElementBuffer = 128 * 1024 + + frametime = time.Second / 30 + + rows = 3 +) + +var ( + white nk.Color + atlas *nk.FontAtlas + sansFont *nk.Font + sansFontHandle *nk.UserFont + ctx *nk.Context + width, height int + y, lastY float32 +) + +func uiInit() { + platformInit() + mkWin() + white = nk.NkRgba(255,255,255,255) + table := []nk.Color{ + nk.NkRgba(70, 70, 70, 255), // NK_COLOR_TEXT + nk.NkRgba(175, 175, 175, 255), // NK_COLOR_WINDOW + nk.NkRgba(175, 175, 175, 255), // NK_COLOR_HEADER + nk.NkRgba(0, 0, 0, 255), // NK_COLOR_BORDER + nk.NkRgba(185, 185, 185, 255), // NK_COLOR_BUTTON + nk.NkRgba(170, 170, 170, 255), // NK_COLOR_BUTTON_HOVER + nk.NkRgba(160, 160, 160, 255), // NK_COLOR_BUTTON_ACTIVE + nk.NkRgba(150, 150, 150, 255), // NK_COLOR_TOGGLE + nk.NkRgba(120, 120, 120, 255), // NK_COLOR_TOGGLE_HOVER + nk.NkRgba(175, 175, 175, 255), // NK_COLOR_TOGGLE_CURSOR + nk.NkRgba(190, 190, 190, 255), // NK_COLOR_SELECT + nk.NkRgba(175, 175, 175, 255), // NK_COLOR_SELECT_ACTIVE + nk.NkRgba(190, 190, 190, 255), // NK_COLOR_SLIDER + nk.NkRgba(80, 80, 80, 255), // NK_COLOR_SLIDER_CURSOR + nk.NkRgba(70, 70, 70, 255), // NK_COLOR_SLIDER_CURSOR_HOVER + nk.NkRgba(60, 60, 60, 255), // NK_COLOR_SLIDER_CURSOR_ACTIVE + nk.NkRgba(175, 175, 175, 255), // NK_COLOR_PROPERTY + nk.NkRgba(150, 150, 150, 255), // NK_COLOR_EDIT + nk.NkRgba(0, 0, 0, 255), // NK_COLOR_EDIT_CURSOR + nk.NkRgba(175, 175, 175, 255), // NK_COLOR_COMBO + nk.NkRgba(160, 160, 160, 255), // NK_COLOR_CHART + nk.NkRgba(45, 45, 45, 255), // NK_COLOR_CHART_COLOR + nk.NkRgba( 255, 0, 0, 255), // NK_COLOR_CHART_COLOR_HIGHLIGHT + nk.NkRgba(180, 180, 180, 255), // NK_COLOR_SCROLLBAR + nk.NkRgba(140, 140, 140, 255), // NK_COLOR_SCROLLBAR_CURSOR + nk.NkRgba(150, 150, 150, 255), // NK_COLOR_SCROLLBAR_CURSOR_HOVER + nk.NkRgba(160, 160, 160, 255), // NK_COLOR_SCROLLBAR_CURSOR_ACTIVE + nk.NkRgba(180, 180, 180, 255), // NK_COLOR_TAB_HEADER + } + _ = table + // this scheme comes out all white on Android. + //nk.NkStyleFromTable(ctx, table) +} + +func loadFont() { + atlas = nk.NewFontAtlas() + nk.NkFontStashBegin(&atlas) + sansFont = nk.NkFontAtlasAddFromBytes(atlas, MustAsset("assets/DroidSans.ttf"), fontSize, nil) + nk.NkFontStashEnd() + if sansFont != nil { + sansFontHandle = sansFont.Handle() + nk.NkStyleSetFont(ctx, sansFontHandle) + } + log(Info, "Font added") +} + +func row(i int32,hs ...int) { + h := 1 + if len(hs) > 0 { + h = hs[0] + } + nk.NkLayoutRowStatic(ctx,float32(height / (h * rows)),int32(float32(-i)+float32(width-25)/float32(i)),i) +} + +func button(text string) bool { + return nk.NkButtonLabel(ctx,text) > 0 +} + +func label(text string, optss ...nk.Flags) { + var opts nk.Flags + if len(optss) > 0 { + opts = optss[0] + } else { + opts = nk.TextAlignLeft | nk.TextAlignMiddle + } + nk.NkLabel(ctx,text,opts) +} + +func editstring(buf []byte) { + nk.NkEditFocus(ctx, nk.EditBox) + nk.NkEditStringZeroTerminated(ctx, nk.EditBox, buf, int32(len(buf)), nk.NkFilterAscii) +} + +func uiBegin() bool { + nk.NkPlatformNewFrame() +// NewFrame() + lastY = y + + width, height = GetSize() + + bounds := nk.NkRect(0,0,float32(width),float32(height)) + ret := nk.NkBegin(ctx, "Rand", bounds, nk.WindowScrollAutoHide) > 0 + wpos := nk.NkWidgetPosition(ctx) + lastY = y + y = wpos.Y() + return ret +} + +func uiEnd() { + nk.NkEnd(ctx) + nk.NkPlatformRender(nk.AntiAliasingOn, maxVertexBuffer, maxElementBuffer) + SwapBuffers() +} + diff --git a/cmd/rand/main.go b/cmd/rand/main.go new file mode 100644 index 0000000..3631a11 --- /dev/null +++ b/cmd/rand/main.go @@ -0,0 +1,70 @@ +package main + +import ( + "fmt" + "os" + "strconv" + + "gitlab.wow.st/gmp/rand" +) + +func usage() { + fmt.Println("rand [-d | -l | -s] [num]") + os.Exit(-1) +} + +func main() { + args := os.Args[1:] + var f func() (byte,error) + var n int + var err error + + func() { + if len(args) == 0 { + f = rand.Char + n = 20 + return + } + if len(args) >= 1 { + switch args[0] { + case "-d","--digits": + f = rand.Digit + case "-l","--letters": + f = rand.Letter + case "-s","--symbols": + f = rand.Symbol + default: + f = rand.Char + n, err = strconv.Atoi(args[0]) + if err != nil { + usage() + } + } + } + switch len(args) { + case 1: + if n == 0 { + n = 20 + } + case 2: + if n != 0 { + usage() + } + n, err = strconv.Atoi(args[1]) + if err != nil { + usage() + } + default: + usage() + } + }() + + s, err := rand.Slice(f,n) + if err != nil { + fmt.Println(err) + os.Exit(-1) + } + os.Stdout.Write(s) + os.Stdout.Write([]byte("\n")) +} + diff --git a/main.go b/main.go new file mode 100644 index 0000000..68532d8 --- /dev/null +++ b/main.go @@ -0,0 +1,50 @@ +package rand + +import ( + "fmt" + crand "crypto/rand" + "math/big" +) + +var chars []byte = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()_+-=[]{}\\|;:'\",./<>?") +var letters []byte = chars[0:52] +var digits []byte = chars[52:62] +var symbols []byte = chars[62:94] + +func gen(s []byte) (byte,error) { + nBig, err := crand.Int(crand.Reader, big.NewInt(int64(len(s)))) + if err != nil { + return 0, fmt.Errorf("Error in crypto/rand: %s",err) + } + x := nBig.Int64() + return s[x], nil +} + +func Letter() (byte,error) { + return gen(letters) +} + +func Digit() (byte,error) { + return gen(digits) +} + +func Symbol() (byte,error) { + return gen(symbols) +} + +func Char() (byte,error) { + return gen(chars) +} + +func Slice(f func() (byte,error), n int) ([]byte,error) { + ret := make([]byte,0) + for i := 0; i < n; i++ { + x,err := f() + if err != nil { + return ret, err + } + ret = append(ret,x) + } + return ret, nil +} +