<commit_before>package cl11

import (
	"fmt"
	"testing"
)

func TestGetDevices(t *testing.T) {
	platforms, err := GetPlatforms()
	if err != nil {
		t.Fatal(err)
	}
	for i := range platforms {
		fmt.Println(platforms[i].Name)
		devices, err := platforms[i].GetDevices()
		if err != nil {
			t.Fatal(err)
		}
		for j := range devices {
			fmt.Println(" ", devices[j].Name)
			fmt.Printf("%+v\n", devices[j])
		}
	}
}
<commit_msg>Removed printing of device info in tests.<commit_after>package cl11

import "testing"

func TestGetDevices(t *testing.T) {
	platforms, err := GetPlatforms()
	if err != nil {
		t.Fatal(err)
	}
	for i := range platforms {
		// fmt.Println(platforms[i].Name)
		/* devices */ _, err := platforms[i].GetDevices()
		if err != nil {
			t.Fatal(err)
		}
		// for j := range devices {
		// 	fmt.Println(" ", devices[j].Name)
		// 	fmt.Printf("%+v\n", devices[j])
		// }
	}
}
<|endoftext|>


<commit_before>package util

import (
	"golang.org/x/sys/windows"

	"unsafe"
)

const (
	errorSuccess = 0

	seFileObject             = 1
	ownerSecurityInformation = 1
	daclSecurityInformation  = 4

	standardRightsRequired = 0xF0000
	grantAccess            = 1
	noInheritance          = 0

	trusteeIsSID = 0
)

var (
	advapi32              = windows.MustLoadDLL("advapi32.dll")
	getNamedSecurityInfoW = advapi32.MustFindProc("GetNamedSecurityInfoW")
	setEntriesInAclW      = advapi32.MustFindProc("SetEntriesInAclW")
	setNamedSecurityInfoW = advapi32.MustFindProc("SetNamedSecurityInfoW")

	kernel32           = windows.MustLoadDLL("kernel32.dll")
	getModuleFileNameW = kernel32.MustFindProc("GetModuleFileNameW")
)

type trustee struct {
	pMultipleTrustee         unsafe.Pointer
	MultipleTrusteeOperation int32
	TrusteeForm              int32
	TrusteeType              int32
	ptstrName                unsafe.Pointer
}

type explicitAccessW struct {
	grfAccessPermissions uint32
	grfAccessMode        int32
	grfInheritance       uint32
	Trustee              trustee
}

// Ensure that the specified path is only accessible to the current user. This
// is accomplished by setting a single ACE in the path's ACL for the owner.
func SecurePath(path string) error {
	var (
		pSID windows.Handle
		pSD  windows.Handle
	)
	ret, _, err := getNamedSecurityInfoW.Call(
		uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(path))),
		uintptr(seFileObject),
		uintptr(ownerSecurityInformation),
		uintptr(unsafe.Pointer(&pSID)),
		uintptr(0),
		uintptr(0),
		uintptr(0),
		uintptr(unsafe.Pointer(&pSD)),
	)
	// TODO: for some reason the error isn't returned
	if ret != errorSuccess {
		return err
	}
	defer windows.LocalFree(pSD)
	var (
		ea = []explicitAccessW{
			{
				grfAccessPermissions: standardRightsRequired,
				grfAccessMode:        grantAccess,
				grfInheritance:       noInheritance,
				Trustee: trustee{
					TrusteeForm: trusteeIsSID,
					ptstrName:   unsafe.Pointer(pSID),
				},
			},
		}
		pACL windows.Handle
	)
	ret, _, err = setEntriesInAclW.Call(
		uintptr(len(ea)),
		uintptr(unsafe.Pointer(&ea[0])),
		uintptr(0),
		uintptr(unsafe.Pointer(&pACL)),
	)
	if ret != errorSuccess {
		return err
	}
	defer windows.LocalFree(pACL)
	ret, _, err = setNamedSecurityInfoW.Call(
		uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(path))),
		uintptr(seFileObject),
		uintptr(daclSecurityInformation),
		uintptr(0),
		uintptr(0),
		uintptr(pACL),
		uintptr(0),
	)
	if ret != errorSuccess {
		return err
	}
	return nil
}

// Retrieve the full path to the current executable using the Windows API.
func Executable() (string, error) {
	s := make([]uint16, windows.MAX_PATH)
	ret, _, err := getModuleFileNameW.Call(
		0,
		uintptr(unsafe.Pointer(&s[0])),
		uintptr(len(s)),
	)
	if ret != 0 {
		return windows.UTF16ToString(s[:ret]), nil
	} else {
		return "", err
	}
}
<commit_msg>Fixed bug with inherited permissions in SecurePath() implementation (#16).<commit_after>package util

import (
	"golang.org/x/sys/windows"

	"unsafe"
)

const (
	errorSuccess = 0

	seFileObject                     = 1
	ownerSecurityInformation         = 1
	daclSecurityInformation          = 4
	protectedDaclSecurityInformation = 0x80000000

	standardRightsRequired = 0xF0000
	grantAccess            = 1
	noInheritance          = 0

	trusteeIsSID = 0
)

var (
	advapi32              = windows.MustLoadDLL("advapi32.dll")
	getNamedSecurityInfoW = advapi32.MustFindProc("GetNamedSecurityInfoW")
	setEntriesInAclW      = advapi32.MustFindProc("SetEntriesInAclW")
	setNamedSecurityInfoW = advapi32.MustFindProc("SetNamedSecurityInfoW")

	kernel32           = windows.MustLoadDLL("kernel32.dll")
	getModuleFileNameW = kernel32.MustFindProc("GetModuleFileNameW")
)

type trustee struct {
	pMultipleTrustee         unsafe.Pointer
	MultipleTrusteeOperation int32
	TrusteeForm              int32
	TrusteeType              int32
	ptstrName                unsafe.Pointer
}

type explicitAccessW struct {
	grfAccessPermissions uint32
	grfAccessMode        int32
	grfInheritance       uint32
	Trustee              trustee
}

// Ensure that the specified path is only accessible to the current user. This
// is accomplished by setting a single ACE in the path's ACL for the owner.
func SecurePath(path string) error {
	var (
		pSID windows.Handle
		pSD  windows.Handle
	)
	ret, _, err := getNamedSecurityInfoW.Call(
		uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(path))),
		uintptr(seFileObject),
		uintptr(ownerSecurityInformation),
		uintptr(unsafe.Pointer(&pSID)),
		uintptr(0),
		uintptr(0),
		uintptr(0),
		uintptr(unsafe.Pointer(&pSD)),
	)
	// TODO: for some reason the error isn't returned
	if ret != errorSuccess {
		return err
	}
	defer windows.LocalFree(pSD)
	var (
		ea = []explicitAccessW{
			{
				grfAccessPermissions: standardRightsRequired,
				grfAccessMode:        grantAccess,
				grfInheritance:       noInheritance,
				Trustee: trustee{
					TrusteeForm: trusteeIsSID,
					ptstrName:   unsafe.Pointer(pSID),
				},
			},
		}
		pACL windows.Handle
	)
	ret, _, err = setEntriesInAclW.Call(
		uintptr(len(ea)),
		uintptr(unsafe.Pointer(&ea[0])),
		uintptr(0),
		uintptr(unsafe.Pointer(&pACL)),
	)
	if ret != errorSuccess {
		return err
	}
	defer windows.LocalFree(pACL)
	ret, _, err = setNamedSecurityInfoW.Call(
		uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(path))),
		uintptr(seFileObject),
		uintptr(daclSecurityInformation|protectedDaclSecurityInformation),
		uintptr(0),
		uintptr(0),
		uintptr(pACL),
		uintptr(0),
	)
	if ret != errorSuccess {
		return err
	}
	return nil
}

// Retrieve the full path to the current executable using the Windows API.
func Executable() (string, error) {
	s := make([]uint16, windows.MAX_PATH)
	ret, _, err := getModuleFileNameW.Call(
		0,
		uintptr(unsafe.Pointer(&s[0])),
		uintptr(len(s)),
	)
	if ret != 0 {
		return windows.UTF16ToString(s[:ret]), nil
	} else {
		return "", err
	}
}
<|endoftext|>


<commit_before>/*
  Copyright David Thorpe 2015-2016 All Rights Reserved
  Please see file LICENSE for information on distribution, etc
*/
package main

import (
    "os"
    "fmt"

    "github.com/djthorpe/ytapi/ytapi"
    "github.com/djthorpe/ytapi/ytcommands"
    "github.com/djthorpe/ytapi/ytservice"
)

////////////////////////////////////////////////////////////////////////////////

func main() {
    // Parse command-line flags
    command, values, err := ytapi.ParseFlags([]ytapi.RegisterFunction{
        ytcommands.RegisterAuthenticateCommands,
        ytcommands.RegisterBroadcastCommands,
    })
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }
    if command == nil {
        os.Exit(2)
    }

    // Read content owner and channel from file
    defaultsPath := ytcommands.GetDefaultsPath(values)
    if err := values.ReadDefaultsFromFile(defaultsPath); err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // call command setup function
    output := ytservice.NewTable()

    if command.Setup != nil {
        if err := command.Setup(values,output); err != nil {
            fmt.Fprintf(os.Stderr, "Error: %v\n", err)
            os.Exit(1)
        }
    }

    // create the service object
    serviceAccountPath := ytcommands.GetServiceAccountPath(values)
    clientSecretPath := ytcommands.GetClientSecretPath(values)
    tokenPath := ytcommands.GetOAuthTokenPath(values)
    debugFlag := values.GetBool(&ytapi.FlagDebug)

    // if the content owner is set, then create an API object from service
    // account, or else create the API object from client secrets and oauth
    // token
    var service *ytservice.Service
    if values.IsSet(&ytapi.FlagContentOwner) {
        service, err = ytservice.NewYouTubeServiceFromServiceAccountJSON(serviceAccountPath,debugFlag)
    } else {
        service, err = ytservice.NewYouTubeServiceFromClientSecretsJSON(clientSecretPath,tokenPath,debugFlag)
    }
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // call command execute function
    if command.Execute != nil {
        if err := command.Execute(service,values,output); err != nil {
            fmt.Fprintf(os.Stderr, "Error: %v\n", err)
            os.Exit(1)
        }
    }
}

/*

var (
	operations = map[string]Operation{
		"Authenticate":    Operation{NoOp, Authenticate},
		"ListVideos":      Operation{NoOp, ytcommands.ListVideos},                                   // --channel=<id> --maxresults=<n>
		"ListBroadcasts":  Operation{ytcommands.RegisterBroadcastFormat, ytcommands.ListBroadcasts}, // --channel=<id> --maxresults=<n>
		"DeleteBroadcast": Operation{NoOp, ytcommands.DeleteBroadcast},                              // --video=<id>
		"ListStreams":     Operation{ytcommands.RegisterStreamFormat, ytcommands.ListStreams},       // --channel=<id> --maxresults=<n>
		"DeleteStream":    Operation{NoOp, ytcommands.DeleteStream},                                 // --stream=<id>
		"Search":          Operation{ytcommands.RegisterSearchFormat, ytcommands.Search},            // --q=<string> --maxresults=<n>

		// Channels
		"ListChannels":                   Operation{ytcommands.RegisterChannelFormat, ytcommands.ListChannels}, // --channel=<id> --maxresults=<n>
		"ListLocalizedChannelMetadata":   Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.ListLocalizedChannelMetadata},
		"UpdateChannelMetadata":          Operation{ytcommands.RegisterChannelFormat, ytcommands.UpdateChannelMetadata},                           // -hl=<string> -title=<string> -description=<string>
		"UpdateLocalizedChannelMetadata": Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.UpdateLocalizedChannelMetadata}, // -hl=<string> -title=<string> -description=<string>

		// Playlists
		"ListPlaylists":                   Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -maxresults=<n>
		"ListLocalizedPlaylistMetadata":   Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -playlist=<id>
		"CreatePlaylist":                  Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -hl=<string> -title=<string> -description=<string> -privacystatus=(public|private|unlisted) -tags=
		"DeletePlaylist":                  Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -playlist=<id>
		"UpdatePlaylistMetadata":          Operation{ytcommands.RegisterPlaylistFormat, ytcommands.UpdatePlaylistMetadata}, // -playlist=<id> -hl=<string> --title=<string> --description=<string> --status=(public|private|unlisted)
		"UpdateLocalizedPlaylistMetadata": Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // --playlist=<id>  -hl=<string> --title=<string> --description=<string>

	}
)
var (
	credentialsFolder      = flag.String("credentials", ".credentials", "Folder containing credentials")
	clientsecretFilename   = flag.String("clientsecret", "client_secret.json", "Client secret filename")
	serviceAccountFilename = flag.String("serviceaccount", "service_account.json", "Service account filename")
	defaultsFilename       = flag.String("defaults", "defaults.json", "Defaults filename")
	tokenFilename          = flag.String("authtoken", "oauth_token", "OAuth token filename")
	flagDebug              = flag.Bool("debug", false, "Show API requests and responses on stderr")

    flagChannel         = flag.String("channel", "", "Channel ID")
	flagContentOwner    = flag.String("contentowner", "", "Content Owner ID")
	flagVideo           = flag.String("video", "", "Video or Broadcast ID")
	flagStream          = flag.String("stream", "", "Stream Key")
	flagMaxResults      = flag.Int64("maxresults", 0, "Maximum results to return (or 0)")
	flagPart            = flag.String("part", "", "Comma-separated list of parts for response")
	flagOutput          = flag.String("output", "ascii", "Output type (csv, ascii)")
	flagBroadcastStatus = flag.String("broadcaststatus", "all", "Broadcast Status (all,upcoming,active,completed)")
	flagQuery           = flag.String("q", "", "Search Query")
	flagTitle           = flag.String("title", "", "Metadata Title")
	flagDescription     = flag.String("description", "", "Metadata Description")
	flagLanguage        = flag.String("hl", "", "Metadata Language")
)

////////////////////////////////////////////////////////////////////////////////

func NewParamsFromFile(filename string) (*ytservice.Params, error) {
	var params *ytservice.Params
	var err error

	// if a file exists, then read it
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		params = ytservice.NewParams()
	} else {
		params, err = ytservice.NewParamsFromJSON(filename)
	}
	if err != nil {
		return nil, err
	}

	return params, nil
}

func CombineParamsWthContentOwnerFlag(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	return copy, nil
}

func CombineParamsWthFlags(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	// copy --channel
	if len(*flagChannel) > 0 {
		copy.Channel = flagChannel
		if copy.IsValidChannel() == false {
			return nil, errors.New("Invalid -channel flag")
		}
	}

	// copy --maxresults
	if *flagMaxResults < 0 {
		return nil, errors.New("Invalid -maxresults flag")
	}
	if *flagMaxResults > 0 {
		copy.MaxResults = *flagMaxResults
	}

	// copy --q
	if len(*flagQuery) > 0 {
		copy.Query = flagQuery
	}

	// copy -video
	if len(*flagVideo) > 0 {
		copy.Video = flagVideo
		if copy.IsValidVideo() == false {
			return nil, errors.New("Invalid -video flag")
		}
	}

	// copy -stream
	if len(*flagStream) > 0 {
		copy.Stream = flagStream
		if copy.IsValidStream() == false {
			return nil, errors.New("Invalid -stream flag")
		}
	}

	// copy -broadcaststatus
	if len(*flagBroadcastStatus) > 0 {
		copy.BroadcastStatus = flagBroadcastStatus
		if copy.IsValidBroadcastStatus() == false {
			return nil, errors.New("Invalid -broadcaststatus flag")
		}
	}

	// copy title & description
	if len(*flagTitle) > 0 {
		copy.Title = flagTitle
	}
	if len(*flagDescription) > 0 {
		copy.Description = flagDescription
	}

	// copy language
	if len(*flagLanguage) > 0 {
		copy.Language = flagLanguage
		if copy.IsValidLanguage() == false {
			return nil, errors.New("Invalid -hl flag")
		}
	}

	return copy, nil
}

func Authenticate(service *ytservice.Service, params *ytservice.Params, output *ytservice.Table) error {

	// output content owner and channel information
	output.AddColumn("contentowner")
	output.AddColumn("channel")
	row := output.NewRow()

	if params.IsEmptyContentOwner() == false {
		row.SetString("contentowner", *params.ContentOwner)
	}
	if params.IsEmptyChannel() == false {
		row.SetString("channel", *params.Channel)
	}

	// success
	return nil
}

func NoOp(params *ytservice.Params, table *ytservice.Table) error {
	// Do Nothing
	return nil
}

func AlterColumnsForParts(parts []string, table *ytservice.Table) error {
	for _, part := range parts {
		if strings.HasPrefix(part, "-") {
			if err := table.RemoveColumnsForPart(strings.TrimPrefix(part, "-")); err != nil {
				return err
			}
		} else if strings.HasPrefix(part, "+") {
			if err := table.AddColumnsForPart(strings.TrimPrefix(part, "+")); err != nil {
				return err
			}
		} else {
			return errors.New("part elements must be prefixed with + or -")
		}
	}
	// success
	return nil
}

////////////////////////////////////////////////////////////////////////////////

func main() {
    var err error

    // Obtain path for credentials - create if not already made
	credentialsPath := filepath.Join(userDir(), *credentialsFolder)
	if credentialsPathInfo, err := os.Stat(credentialsPath); err != nil || !credentialsPathInfo.IsDir() {
		// if path is missing, try and create the folder
		if err := os.Mkdir(credentialsPath, credentialsPathMode); err != nil {
			fmt.Fprintf(os.Stderr, "Missing credentials folder: %v\n", credentialsPath)
			os.Exit(1)
		}
	}

    // Create params object
    defaultsPath := filepath.Join(credentialsPath, *defaultsFilename)
    params, err := NewParamsFromFile(defaultsPath)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // Check Flags
    err = InitParamsFromCommandLine(params)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

	var api *ytservice.Service

    // if operation is to authenticate, delete existing token
	tokenPath := filepath.Join(credentialsPath, *tokenFilename)
	if opname == "Authenticate" {
		// Delete OAuth token
		if _, err := os.Stat(tokenPath); os.IsNotExist(err) == false {
			err = os.Remove(tokenPath)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %v\n", err)
				os.Exit(1)
			}
		}
	}

	// Combine content owner flag
	defaults, err = CombineParamsWthContentOwnerFlag(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Authenticate
	serviceAccountPath := filepath.Join(credentialsPath, *serviceAccountFilename)
	clientSecretPath := filepath.Join(credentialsPath, *clientsecretFilename)
	if defaults.IsEmptyContentOwner() == false {
		api, err = ytservice.NewYouTubeServiceFromServiceAccountJSON(serviceAccountPath, defaults, *flagDebug)
	} else {
		api, err = ytservice.NewYouTubeServiceFromClientSecretsJSON(clientSecretPath, tokenPath, defaults, *flagDebug)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// If this isn't a service account and no channel parameter is set, then
	// set the channel parameter
	if api.ServiceAccount == false && defaults.IsValidChannel() == false {
		call := api.API.Channels.List("id").Mine(true)
		response, err := call.MaxResults(1).Do()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(response.Items) > 0 {
			defaults.Channel = &response.Items[0].Id
		}
	}

	// Save Defaults
	defaults.Save(defaultsPath, credentialsFileMode)

	// Combine defaults with command-line flags to make parameters
	params, err := CombineParamsWthFlags(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

    // Check flags
    if err := params.CheckFlags(flag.Arg(0)); err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

	// Create a table object
	output := ytservice.NewTable()

    // Setup
	err = operations[opname].setup(params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Add and remove parts
	if len(*flagPart) > 0 {
		err = AlterColumnsForParts(strings.Split(*flagPart, ","), output)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Execute
	err = operations[opname].do(api, params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

    // Output results
	if *flagOutput == "ascii" {
		err = output.ASCII(os.Stdout)
	} else if *flagOutput == "csv" {
		err = output.CSV(os.Stdout)
	} else {
		err = errors.New("Invalid --output flag")
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

*/
<commit_msg>Updated<commit_after>/*
  Copyright David Thorpe 2015-2016 All Rights Reserved
  Please see file LICENSE for information on distribution, etc
*/
package main

import (
    "os"
    "fmt"

    "github.com/djthorpe/ytapi/ytapi"
    "github.com/djthorpe/ytapi/ytcommands"
    "github.com/djthorpe/ytapi/ytservice"
)

////////////////////////////////////////////////////////////////////////////////

func main() {
    // Parse command-line flags
    command, values, err := ytapi.ParseFlags([]ytapi.RegisterFunction{
        ytcommands.RegisterAuthenticateCommands,
        ytcommands.RegisterBroadcastCommands,
    })
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }
    if command == nil {
        os.Exit(2)
    }

    // Read content owner and channel from file
    defaultsPath := ytcommands.GetDefaultsPath(values)
    if err := values.ReadDefaultsFromFile(defaultsPath); err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // call command setup function
    output := ytservice.NewTable()
    if command.Setup != nil {
        if err := command.Setup(values,output); err != nil {
            fmt.Fprintf(os.Stderr, "Error: %v\n", err)
            os.Exit(1)
        }
    }

    // create the service object
    serviceAccountPath := ytcommands.GetServiceAccountPath(values)
    clientSecretPath := ytcommands.GetClientSecretPath(values)
    tokenPath := ytcommands.GetOAuthTokenPath(values)
    debugFlag := values.GetBool(&ytapi.FlagDebug)

    // if the content owner is set, then create an API object from service
    // account, or else create the API object from client secrets and oauth
    // token
    var service *ytservice.Service
    if values.IsSet(&ytapi.FlagContentOwner) {
        service, err = ytservice.NewYouTubeServiceFromServiceAccountJSON(serviceAccountPath,debugFlag)
    } else {
        service, err = ytservice.NewYouTubeServiceFromClientSecretsJSON(clientSecretPath,tokenPath,debugFlag)
    }
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // call command execute function
    if command.Execute != nil {
        if err := command.Execute(service,values,output); err != nil {
            fmt.Fprintf(os.Stderr, "Error: %v\n", err)
            os.Exit(1)
        }
    }
}

/*

var (
	operations = map[string]Operation{
		"Authenticate":    Operation{NoOp, Authenticate},
		"ListVideos":      Operation{NoOp, ytcommands.ListVideos},                                   // --channel=<id> --maxresults=<n>
		"ListBroadcasts":  Operation{ytcommands.RegisterBroadcastFormat, ytcommands.ListBroadcasts}, // --channel=<id> --maxresults=<n>
		"DeleteBroadcast": Operation{NoOp, ytcommands.DeleteBroadcast},                              // --video=<id>
		"ListStreams":     Operation{ytcommands.RegisterStreamFormat, ytcommands.ListStreams},       // --channel=<id> --maxresults=<n>
		"DeleteStream":    Operation{NoOp, ytcommands.DeleteStream},                                 // --stream=<id>
		"Search":          Operation{ytcommands.RegisterSearchFormat, ytcommands.Search},            // --q=<string> --maxresults=<n>

		// Channels
		"ListChannels":                   Operation{ytcommands.RegisterChannelFormat, ytcommands.ListChannels}, // --channel=<id> --maxresults=<n>
		"ListLocalizedChannelMetadata":   Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.ListLocalizedChannelMetadata},
		"UpdateChannelMetadata":          Operation{ytcommands.RegisterChannelFormat, ytcommands.UpdateChannelMetadata},                           // -hl=<string> -title=<string> -description=<string>
		"UpdateLocalizedChannelMetadata": Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.UpdateLocalizedChannelMetadata}, // -hl=<string> -title=<string> -description=<string>

		// Playlists
		"ListPlaylists":                   Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -maxresults=<n>
		"ListLocalizedPlaylistMetadata":   Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -playlist=<id>
		"CreatePlaylist":                  Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -hl=<string> -title=<string> -description=<string> -privacystatus=(public|private|unlisted) -tags=
		"DeletePlaylist":                  Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // -playlist=<id>
		"UpdatePlaylistMetadata":          Operation{ytcommands.RegisterPlaylistFormat, ytcommands.UpdatePlaylistMetadata}, // -playlist=<id> -hl=<string> --title=<string> --description=<string> --status=(public|private|unlisted)
		"UpdateLocalizedPlaylistMetadata": Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists}, // --playlist=<id>  -hl=<string> --title=<string> --description=<string>

	}
)
var (
	credentialsFolder      = flag.String("credentials", ".credentials", "Folder containing credentials")
	clientsecretFilename   = flag.String("clientsecret", "client_secret.json", "Client secret filename")
	serviceAccountFilename = flag.String("serviceaccount", "service_account.json", "Service account filename")
	defaultsFilename       = flag.String("defaults", "defaults.json", "Defaults filename")
	tokenFilename          = flag.String("authtoken", "oauth_token", "OAuth token filename")
	flagDebug              = flag.Bool("debug", false, "Show API requests and responses on stderr")

    flagChannel         = flag.String("channel", "", "Channel ID")
	flagContentOwner    = flag.String("contentowner", "", "Content Owner ID")
	flagVideo           = flag.String("video", "", "Video or Broadcast ID")
	flagStream          = flag.String("stream", "", "Stream Key")
	flagMaxResults      = flag.Int64("maxresults", 0, "Maximum results to return (or 0)")
	flagPart            = flag.String("part", "", "Comma-separated list of parts for response")
	flagOutput          = flag.String("output", "ascii", "Output type (csv, ascii)")
	flagBroadcastStatus = flag.String("broadcaststatus", "all", "Broadcast Status (all,upcoming,active,completed)")
	flagQuery           = flag.String("q", "", "Search Query")
	flagTitle           = flag.String("title", "", "Metadata Title")
	flagDescription     = flag.String("description", "", "Metadata Description")
	flagLanguage        = flag.String("hl", "", "Metadata Language")
)

////////////////////////////////////////////////////////////////////////////////

func NewParamsFromFile(filename string) (*ytservice.Params, error) {
	var params *ytservice.Params
	var err error

	// if a file exists, then read it
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		params = ytservice.NewParams()
	} else {
		params, err = ytservice.NewParamsFromJSON(filename)
	}
	if err != nil {
		return nil, err
	}

	return params, nil
}

func CombineParamsWthContentOwnerFlag(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	return copy, nil
}

func CombineParamsWthFlags(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	// copy --channel
	if len(*flagChannel) > 0 {
		copy.Channel = flagChannel
		if copy.IsValidChannel() == false {
			return nil, errors.New("Invalid -channel flag")
		}
	}

	// copy --maxresults
	if *flagMaxResults < 0 {
		return nil, errors.New("Invalid -maxresults flag")
	}
	if *flagMaxResults > 0 {
		copy.MaxResults = *flagMaxResults
	}

	// copy --q
	if len(*flagQuery) > 0 {
		copy.Query = flagQuery
	}

	// copy -video
	if len(*flagVideo) > 0 {
		copy.Video = flagVideo
		if copy.IsValidVideo() == false {
			return nil, errors.New("Invalid -video flag")
		}
	}

	// copy -stream
	if len(*flagStream) > 0 {
		copy.Stream = flagStream
		if copy.IsValidStream() == false {
			return nil, errors.New("Invalid -stream flag")
		}
	}

	// copy -broadcaststatus
	if len(*flagBroadcastStatus) > 0 {
		copy.BroadcastStatus = flagBroadcastStatus
		if copy.IsValidBroadcastStatus() == false {
			return nil, errors.New("Invalid -broadcaststatus flag")
		}
	}

	// copy title & description
	if len(*flagTitle) > 0 {
		copy.Title = flagTitle
	}
	if len(*flagDescription) > 0 {
		copy.Description = flagDescription
	}

	// copy language
	if len(*flagLanguage) > 0 {
		copy.Language = flagLanguage
		if copy.IsValidLanguage() == false {
			return nil, errors.New("Invalid -hl flag")
		}
	}

	return copy, nil
}

func Authenticate(service *ytservice.Service, params *ytservice.Params, output *ytservice.Table) error {

	// output content owner and channel information
	output.AddColumn("contentowner")
	output.AddColumn("channel")
	row := output.NewRow()

	if params.IsEmptyContentOwner() == false {
		row.SetString("contentowner", *params.ContentOwner)
	}
	if params.IsEmptyChannel() == false {
		row.SetString("channel", *params.Channel)
	}

	// success
	return nil
}

func NoOp(params *ytservice.Params, table *ytservice.Table) error {
	// Do Nothing
	return nil
}

func AlterColumnsForParts(parts []string, table *ytservice.Table) error {
	for _, part := range parts {
		if strings.HasPrefix(part, "-") {
			if err := table.RemoveColumnsForPart(strings.TrimPrefix(part, "-")); err != nil {
				return err
			}
		} else if strings.HasPrefix(part, "+") {
			if err := table.AddColumnsForPart(strings.TrimPrefix(part, "+")); err != nil {
				return err
			}
		} else {
			return errors.New("part elements must be prefixed with + or -")
		}
	}
	// success
	return nil
}

////////////////////////////////////////////////////////////////////////////////

func main() {
    var err error

    // Obtain path for credentials - create if not already made
	credentialsPath := filepath.Join(userDir(), *credentialsFolder)
	if credentialsPathInfo, err := os.Stat(credentialsPath); err != nil || !credentialsPathInfo.IsDir() {
		// if path is missing, try and create the folder
		if err := os.Mkdir(credentialsPath, credentialsPathMode); err != nil {
			fmt.Fprintf(os.Stderr, "Missing credentials folder: %v\n", credentialsPath)
			os.Exit(1)
		}
	}

    // Create params object
    defaultsPath := filepath.Join(credentialsPath, *defaultsFilename)
    params, err := NewParamsFromFile(defaultsPath)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // Check Flags
    err = InitParamsFromCommandLine(params)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

	var api *ytservice.Service

    // if operation is to authenticate, delete existing token
	tokenPath := filepath.Join(credentialsPath, *tokenFilename)
	if opname == "Authenticate" {
		// Delete OAuth token
		if _, err := os.Stat(tokenPath); os.IsNotExist(err) == false {
			err = os.Remove(tokenPath)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %v\n", err)
				os.Exit(1)
			}
		}
	}

	// Combine content owner flag
	defaults, err = CombineParamsWthContentOwnerFlag(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Authenticate
	serviceAccountPath := filepath.Join(credentialsPath, *serviceAccountFilename)
	clientSecretPath := filepath.Join(credentialsPath, *clientsecretFilename)
	if defaults.IsEmptyContentOwner() == false {
		api, err = ytservice.NewYouTubeServiceFromServiceAccountJSON(serviceAccountPath, defaults, *flagDebug)
	} else {
		api, err = ytservice.NewYouTubeServiceFromClientSecretsJSON(clientSecretPath, tokenPath, defaults, *flagDebug)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// If this isn't a service account and no channel parameter is set, then
	// set the channel parameter
	if api.ServiceAccount == false && defaults.IsValidChannel() == false {
		call := api.API.Channels.List("id").Mine(true)
		response, err := call.MaxResults(1).Do()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(response.Items) > 0 {
			defaults.Channel = &response.Items[0].Id
		}
	}

	// Save Defaults
	defaults.Save(defaultsPath, credentialsFileMode)

	// Combine defaults with command-line flags to make parameters
	params, err := CombineParamsWthFlags(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

    // Check flags
    if err := params.CheckFlags(flag.Arg(0)); err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

	// Create a table object
	output := ytservice.NewTable()

    // Setup
	err = operations[opname].setup(params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Add and remove parts
	if len(*flagPart) > 0 {
		err = AlterColumnsForParts(strings.Split(*flagPart, ","), output)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Execute
	err = operations[opname].do(api, params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

    // Output results
	if *flagOutput == "ascii" {
		err = output.ASCII(os.Stdout)
	} else if *flagOutput == "csv" {
		err = output.CSV(os.Stdout)
	} else {
		err = errors.New("Invalid --output flag")
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

*/
<|endoftext|>


<commit_before>package zk

/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -lzookeeper_mt

#include <zookeeper/zookeeper.h>

void my_global_watcher(
  zhandle_t *zh,
  int type,
  int state,
  const char* path,
  void *ctx) {
}

extern void GoWatcher(int type, int state, void* path, void* ctx);

void my_watcher(
  zhandle_t *zh,
  int type,
  int state,
  const char* path,
  void *ctx) {
  GoWatcher(type, state, (void*)path, ctx);
}

void my_void_completion(int rc, const void *data) {
}

extern void GoStatCompletion(int rc, void* stat, void* data);

void my_stat_completion(int rc, const struct Stat *stat, const void *data) {
  GoStatCompletion(rc, (void*)stat, (void*)data);
}

extern void GoDataCompletion(
  int rc, void* value, int value_len, void* stat, void* data);

void my_data_completion(int rc, const char *value, int value_len,
       const struct Stat *stat, const void *data) {
  GoDataCompletion(rc, (void*)value, value_len, (void*)stat, (void*)data);
}

void my_strings_completion(int rc,
       const struct String_vector *strings, const void *data) {
}

void my_strings_stat_completion(int rc,
       const struct String_vector *strings, const struct Stat *stat,
       const void *data) {
}

void my_string_completion(int rc, const char *value, const void *data) {
}

void my_acl_completion(int rc, struct ACL_vector *acl,
       struct Stat *stat, const void *data) {
}
*/
import "C"

import (
	"unsafe"
)

// Zookeeper return code.
const (
	ZOK = C.ZOK

	/** System and server-side errors.
	 * This is never thrown by the server, it shouldn't be used other than
	 * to indicate a range. Specifically error codes greater than this
	 * value, but lesser than {@link #ZAPIERROR}, are system errors. */
	ZSYSTEMERROR = C.ZSYSTEMERROR
	ZRUNTIMEINCONSISTENCY = C.ZRUNTIMEINCONSISTENCY
	ZDATAINCONSISTENCY = C.ZDATAINCONSISTENCY
	ZCONNECTIONLOSS = C.ZCONNECTIONLOSS
	ZMARSHALLINGERROR = C.ZMARSHALLINGERROR
	ZUNIMPLEMENTED = C.ZUNIMPLEMENTED
	ZOPERATIONTIMEOUT = C.ZOPERATIONTIMEOUT
	ZBADARGUMENTS = C.ZBADARGUMENTS
	ZINVALIDSTATE = C.ZINVALIDSTATE

	/** API errors.
	 * This is never thrown by the server, it shouldn't be used other than
	 * to indicate a range. Specifically error codes greater than this
	 * value are API errors (while values less than this indicate a
	 * {@link #ZSYSTEMERROR}).
	 */
	ZAPIERROR = C.ZAPIERROR
	ZNONODE = C.ZNONODE
	ZNOAUTH = C.ZNOAUTH
	ZBADVERSION = C.ZBADVERSION
	ZNOCHILDRENFOREPHEMERALS = C.ZNOCHILDRENFOREPHEMERALS
	ZNODEEXISTS = C.ZNODEEXISTS
	ZNOTEMPTY = C.ZNOTEMPTY
	ZSESSIONEXPIRED = C.ZSESSIONEXPIRED
	ZINVALIDCALLBACK = C.ZINVALIDCALLBACK
	ZINVALIDACL = C.ZINVALIDACL
	ZAUTHFAILED = C.ZAUTHFAILED
	ZCLOSING = C.ZCLOSING
	ZNOTHING = C.ZNOTHING
	ZSESSIONMOVED = C.ZSESSIONMOVED
)

/** Zookeeper ACL constants */
var (
	/** This is a completely open ACL*/
	ZOO_OPEN_ACL *C.struct_ACL_vector = &C.ZOO_OPEN_ACL_UNSAFE
	/** This ACL gives the world the ability to read. */
	ZOO_READ_ACL *C.struct_ACL_vector = &C.ZOO_READ_ACL_UNSAFE
	/** This ACL gives the creators authentication id's all permissions. */
	ZOO_CREATOR_ALL_ACL *C.struct_ACL_vector = &C.ZOO_CREATOR_ALL_ACL
)

/**
 * @name Create Flags
 *
 * These flags are used by zoo_create to affect node create. They may
 * be ORed together to combine effects.
 */
var (
	ZOO_EPHEMERAL = C.ZOO_EPHEMERAL
	ZOO_SEQUENCE = C.ZOO_SEQUENCE
)

/**
 * @name State Consts
 * These constants represent the states of a zookeeper connection. They are
 * possible parameters of the watcher callback.
 */
var (
	ZOO_EXPIRED_SESSION_STATE = C.ZOO_EXPIRED_SESSION_STATE
	ZOO_AUTH_FAILED_STATE = C.ZOO_AUTH_FAILED_STATE
	ZOO_CONNECTING_STATE = C.ZOO_CONNECTING_STATE
	ZOO_ASSOCIATING_STATE = C.ZOO_ASSOCIATING_STATE
	ZOO_CONNECTED_STATE = C.ZOO_CONNECTED_STATE
)

/**
 * @name Watch Types
 * These constants indicate the event that caused the watch event. They are
 * possible values of the first parameter of the watcher callback.
 */
var (
	/**
	 * \brief a node has been created.
	 *
	 * This is only generated by watches on non-existent nodes. These watches
	 * are set using \ref zoo_exists.
	 */
	ZOO_CREATED_EVENT = C.ZOO_CREATED_EVENT
	/**
	 * \brief a node has been deleted.
	 *
	 * This is only generated by watches on nodes. These watches
	 * are set using \ref zoo_exists and \ref zoo_get.
	 */
	ZOO_DELETED_EVENT = C.ZOO_DELETED_EVENT
	/**
	 * \brief a node has changed.
	 *
	 * This is only generated by watches on nodes. These watches
	 * are set using \ref zoo_exists and \ref zoo_get.
	 */
	ZOO_CHANGED_EVENT = C.ZOO_CHANGED_EVENT
	/**
	 * \brief a change as occurred in the list of children.
	 *
	 * This is only generated by watches on the child list of a node. These watches
	 * are set using \ref zoo_get_children or \ref zoo_get_children2.
	 */
	ZOO_CHILD_EVENT = C.ZOO_CHILD_EVENT
	/**
	 * \brief a session has been lost.
	 *
	 * This is generated when a client loses contact or reconnects with a server.
	 */
	ZOO_SESSION_EVENT = C.ZOO_SESSION_EVENT
	/**
	 * \brief a watch has been removed.
	 *
	 * This is generated when the server for some reason, probably a resource
	 * constraint, will no longer watch a node for a client.
	 */
	ZOO_NOTWATCHING_EVENT = C.ZOO_NOTWATCHING_EVENT
)

type Watcher struct {
	Type int
	State int
	Path string
}

type StatResult struct {
	rc C.int
	stat C.struct_Stat
}

func (sr *StatResult) GetRc() int {
	return int(sr.rc)
}

func (sr *StatResult) GetCtime() int64 {
	return int64(sr.stat.ctime)
}

func (sr *StatResult) GetMtime() int64 {
	return int64(sr.stat.mtime)
}

func (sr *StatResult) GetVersion() int32 {
	return int32(sr.stat.version)
}

func (sr *StatResult) GetCversion() int32 {
	return int32(sr.stat.cversion)
}

func (sr *StatResult) GetAversion() int32 {
	return int32(sr.stat.aversion)
}

func (sr *StatResult) GetEphemeralOwner() int64 {
	return int64(sr.stat.ephemeralOwner)
}

func (sr *StatResult) GetDataLength() int32 {
	return int32(sr.stat.dataLength)
}

func (sr *StatResult) GetNumChildren() int32 {
	return int32(sr.stat.numChildren)
}

type DataResult struct {
	rc C.int
	data []byte
	stat C.struct_Stat
}

func (sr *DataResult) GetData() []byte {
	return sr.data
}

func (sr *DataResult) GetRc() int {
	return int(sr.rc)
}

func (sr *DataResult) GetCtime() int64 {
	return int64(sr.stat.ctime)
}

func (sr *DataResult) GetMtime() int64 {
	return int64(sr.stat.mtime)
}

func (sr *DataResult) GetVersion() int32 {
	return int32(sr.stat.version)
}

func (sr *DataResult) GetCversion() int32 {
	return int32(sr.stat.cversion)
}

func (sr *DataResult) GetAversion() int32 {
	return int32(sr.stat.aversion)
}

func (sr *DataResult) GetEphemeralOwner() int64 {
	return int64(sr.stat.ephemeralOwner)
}

func (sr *DataResult) GetDataLength() int32 {
	return int32(sr.stat.dataLength)
}

func (sr *DataResult) GetNumChildren() int32 {
	return int32(sr.stat.numChildren)
}

func GoWatcher2(Type C.int, state C.int, path unsafe.Pointer, ctx unsafe.Pointer) {
	watcher := Watcher{
		Type: int(Type),
		State: int(state),
		Path: C.GoString((*C.char)(path)),
	}
	ch := (*chan Watcher)(ctx)
	(*ch) <- watcher
}

func GoStatCompletion2(rc C.int, vstat unsafe.Pointer, data unsafe.Pointer) {
	stat := (*C.struct_Stat)(vstat)
	ch := (*chan StatResult)(data)
	result := StatResult{
		rc : rc,
		stat : *stat,
	}
	(*ch) <-result
}

func GoDataCompletion2(
	rc C.int,
	value unsafe.Pointer,
	value_len C.int,
	stat, data unsafe.Pointer) {

	ch := (*chan DataResult)(data)
	result := DataResult{
		rc: rc,
		data: C.GoBytes(value, value_len),
		stat: *(*C.struct_Stat)(stat),
	}

	(*ch) <-result
}

type ZkID struct {
	id C.clientid_t
}

type ZHandle struct {
	handle *C.zhandle_t
}

/**
 * \brief create a new Zookeeper handle.
 *
 * The return value is the zookeeper handle.
 */
func NewZHandle(hosts string, recvTimeout int, id *ZkID) (h ZHandle, ok bool) {
	chosts := C.CString(hosts)
	defer C.free(unsafe.Pointer(chosts))

	handle, err := C.zookeeper_init(
		chosts, (C.watcher_fn)(C.my_global_watcher), C.int(recvTimeout), &id.id, nil, 0)

	if err != nil {
		ok = false
	} else {
		ok = true
		h = ZHandle{handle: handle}
	}
	return
}

/**
 * \brief get the state of the zookeeper connection.
 *
 * The return value will be one of the \ref State Consts.
 */
func (zh ZHandle) GetState() int {
	return int(C.zoo_state(zh.handle))
}

/**
 * \brief checks the existence of a node in zookeeper.
 *
 */
func (zh ZHandle) Exists(path string) StatResult {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res := make(chan StatResult, 1)
	rc,err := C.zoo_awexists(
		zh.handle,
		cpath,
		nil,
		nil,
		C.stat_completion_t(C.my_stat_completion),
		unsafe.Pointer(&res))

	var ret StatResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res
	}

	return ret
}

/**
 * \brief checks the existence of a node in zookeeper.
 *
 */
func (zh ZHandle) ExistsW(path string) (StatResult, chan Watcher) {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res1 := make(chan StatResult, 1)
	res2 := make(chan Watcher, 1)

	rc,err := C.zoo_awexists(
		zh.handle,
		cpath,
		C.watcher_fn(C.my_watcher),
		unsafe.Pointer(&res2),
		C.stat_completion_t(C.my_stat_completion),
		unsafe.Pointer(&res1))

	var ret StatResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res1
	}

	return ret, res2
}

/**
 * \brief gets the data associated with a node.
 */
func (zh ZHandle) Get(path string) DataResult {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res := make(chan DataResult, 1)
	rc,err := C.zoo_awget(
		zh.handle,
		cpath,
		nil,
		nil,
		C.data_completion_t(C.my_data_completion),
		unsafe.Pointer(&res))

	var ret DataResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res
	}

	return ret
}

/**
 * \brief gets the data associated with a node.
 */
func (zh ZHandle) GetW(path string) (DataResult, chan Watcher) {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res1 := make(chan DataResult, 1)
	res2 := make(chan Watcher, 1)

	rc,err := C.zoo_awget(
		zh.handle,
		cpath,
		C.watcher_fn(C.my_watcher),
		unsafe.Pointer(&res2),
		C.data_completion_t(C.my_data_completion),
		unsafe.Pointer(&res1))

	var ret DataResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res1
	}

	return ret, res2
}
<commit_msg>Implement set<commit_after>package zk

/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -lzookeeper_mt

#include <zookeeper/zookeeper.h>

void my_global_watcher(
  zhandle_t *zh,
  int type,
  int state,
  const char* path,
  void *ctx) {
}

extern void GoWatcher(int type, int state, void* path, void* ctx);

void my_watcher(
  zhandle_t *zh,
  int type,
  int state,
  const char* path,
  void *ctx) {
  GoWatcher(type, state, (void*)path, ctx);
}

void my_void_completion(int rc, const void *data) {
}

extern void GoStatCompletion(int rc, void* stat, void* data);

void my_stat_completion(int rc, const struct Stat *stat, const void *data) {
  GoStatCompletion(rc, (void*)stat, (void*)data);
}

extern void GoDataCompletion(
  int rc, void* value, int value_len, void* stat, void* data);

void my_data_completion(int rc, const char *value, int value_len,
       const struct Stat *stat, const void *data) {
  GoDataCompletion(rc, (void*)value, value_len, (void*)stat, (void*)data);
}

void my_strings_completion(int rc,
       const struct String_vector *strings, const void *data) {
}

void my_strings_stat_completion(int rc,
       const struct String_vector *strings, const struct Stat *stat,
       const void *data) {
}

void my_string_completion(int rc, const char *value, const void *data) {
}

void my_acl_completion(int rc, struct ACL_vector *acl,
       struct Stat *stat, const void *data) {
}
*/
import "C"

import (
	"unsafe"
)

// Zookeeper return code.
const (
	ZOK = C.ZOK

	/** System and server-side errors.
	 * This is never thrown by the server, it shouldn't be used other than
	 * to indicate a range. Specifically error codes greater than this
	 * value, but lesser than {@link #ZAPIERROR}, are system errors. */
	ZSYSTEMERROR = C.ZSYSTEMERROR
	ZRUNTIMEINCONSISTENCY = C.ZRUNTIMEINCONSISTENCY
	ZDATAINCONSISTENCY = C.ZDATAINCONSISTENCY
	ZCONNECTIONLOSS = C.ZCONNECTIONLOSS
	ZMARSHALLINGERROR = C.ZMARSHALLINGERROR
	ZUNIMPLEMENTED = C.ZUNIMPLEMENTED
	ZOPERATIONTIMEOUT = C.ZOPERATIONTIMEOUT
	ZBADARGUMENTS = C.ZBADARGUMENTS
	ZINVALIDSTATE = C.ZINVALIDSTATE

	/** API errors.
	 * This is never thrown by the server, it shouldn't be used other than
	 * to indicate a range. Specifically error codes greater than this
	 * value are API errors (while values less than this indicate a
	 * {@link #ZSYSTEMERROR}).
	 */
	ZAPIERROR = C.ZAPIERROR
	ZNONODE = C.ZNONODE
	ZNOAUTH = C.ZNOAUTH
	ZBADVERSION = C.ZBADVERSION
	ZNOCHILDRENFOREPHEMERALS = C.ZNOCHILDRENFOREPHEMERALS
	ZNODEEXISTS = C.ZNODEEXISTS
	ZNOTEMPTY = C.ZNOTEMPTY
	ZSESSIONEXPIRED = C.ZSESSIONEXPIRED
	ZINVALIDCALLBACK = C.ZINVALIDCALLBACK
	ZINVALIDACL = C.ZINVALIDACL
	ZAUTHFAILED = C.ZAUTHFAILED
	ZCLOSING = C.ZCLOSING
	ZNOTHING = C.ZNOTHING
	ZSESSIONMOVED = C.ZSESSIONMOVED
)

/** Zookeeper ACL constants */
var (
	/** This is a completely open ACL*/
	ZOO_OPEN_ACL *C.struct_ACL_vector = &C.ZOO_OPEN_ACL_UNSAFE
	/** This ACL gives the world the ability to read. */
	ZOO_READ_ACL *C.struct_ACL_vector = &C.ZOO_READ_ACL_UNSAFE
	/** This ACL gives the creators authentication id's all permissions. */
	ZOO_CREATOR_ALL_ACL *C.struct_ACL_vector = &C.ZOO_CREATOR_ALL_ACL
)

/**
 * @name Create Flags
 *
 * These flags are used by zoo_create to affect node create. They may
 * be ORed together to combine effects.
 */
var (
	ZOO_EPHEMERAL = C.ZOO_EPHEMERAL
	ZOO_SEQUENCE = C.ZOO_SEQUENCE
)

/**
 * @name State Consts
 * These constants represent the states of a zookeeper connection. They are
 * possible parameters of the watcher callback.
 */
var (
	ZOO_EXPIRED_SESSION_STATE = C.ZOO_EXPIRED_SESSION_STATE
	ZOO_AUTH_FAILED_STATE = C.ZOO_AUTH_FAILED_STATE
	ZOO_CONNECTING_STATE = C.ZOO_CONNECTING_STATE
	ZOO_ASSOCIATING_STATE = C.ZOO_ASSOCIATING_STATE
	ZOO_CONNECTED_STATE = C.ZOO_CONNECTED_STATE
)

/**
 * @name Watch Types
 * These constants indicate the event that caused the watch event. They are
 * possible values of the first parameter of the watcher callback.
 */
var (
	/**
	 * \brief a node has been created.
	 *
	 * This is only generated by watches on non-existent nodes. These watches
	 * are set using \ref zoo_exists.
	 */
	ZOO_CREATED_EVENT = C.ZOO_CREATED_EVENT
	/**
	 * \brief a node has been deleted.
	 *
	 * This is only generated by watches on nodes. These watches
	 * are set using \ref zoo_exists and \ref zoo_get.
	 */
	ZOO_DELETED_EVENT = C.ZOO_DELETED_EVENT
	/**
	 * \brief a node has changed.
	 *
	 * This is only generated by watches on nodes. These watches
	 * are set using \ref zoo_exists and \ref zoo_get.
	 */
	ZOO_CHANGED_EVENT = C.ZOO_CHANGED_EVENT
	/**
	 * \brief a change as occurred in the list of children.
	 *
	 * This is only generated by watches on the child list of a node. These watches
	 * are set using \ref zoo_get_children or \ref zoo_get_children2.
	 */
	ZOO_CHILD_EVENT = C.ZOO_CHILD_EVENT
	/**
	 * \brief a session has been lost.
	 *
	 * This is generated when a client loses contact or reconnects with a server.
	 */
	ZOO_SESSION_EVENT = C.ZOO_SESSION_EVENT
	/**
	 * \brief a watch has been removed.
	 *
	 * This is generated when the server for some reason, probably a resource
	 * constraint, will no longer watch a node for a client.
	 */
	ZOO_NOTWATCHING_EVENT = C.ZOO_NOTWATCHING_EVENT
)

type Watcher struct {
	Type int
	State int
	Path string
}

type StatResult struct {
	rc C.int
	stat C.struct_Stat
}

func (sr *StatResult) GetRc() int {
	return int(sr.rc)
}

func (sr *StatResult) GetCtime() int64 {
	return int64(sr.stat.ctime)
}

func (sr *StatResult) GetMtime() int64 {
	return int64(sr.stat.mtime)
}

func (sr *StatResult) GetVersion() int32 {
	return int32(sr.stat.version)
}

func (sr *StatResult) GetCversion() int32 {
	return int32(sr.stat.cversion)
}

func (sr *StatResult) GetAversion() int32 {
	return int32(sr.stat.aversion)
}

func (sr *StatResult) GetEphemeralOwner() int64 {
	return int64(sr.stat.ephemeralOwner)
}

func (sr *StatResult) GetDataLength() int32 {
	return int32(sr.stat.dataLength)
}

func (sr *StatResult) GetNumChildren() int32 {
	return int32(sr.stat.numChildren)
}

type DataResult struct {
	rc C.int
	data []byte
	stat C.struct_Stat
}

func (sr *DataResult) GetData() []byte {
	return sr.data
}

func (sr *DataResult) GetRc() int {
	return int(sr.rc)
}

func (sr *DataResult) GetCtime() int64 {
	return int64(sr.stat.ctime)
}

func (sr *DataResult) GetMtime() int64 {
	return int64(sr.stat.mtime)
}

func (sr *DataResult) GetVersion() int32 {
	return int32(sr.stat.version)
}

func (sr *DataResult) GetCversion() int32 {
	return int32(sr.stat.cversion)
}

func (sr *DataResult) GetAversion() int32 {
	return int32(sr.stat.aversion)
}

func (sr *DataResult) GetEphemeralOwner() int64 {
	return int64(sr.stat.ephemeralOwner)
}

func (sr *DataResult) GetDataLength() int32 {
	return int32(sr.stat.dataLength)
}

func (sr *DataResult) GetNumChildren() int32 {
	return int32(sr.stat.numChildren)
}

func GoWatcher2(Type C.int, state C.int, path unsafe.Pointer, ctx unsafe.Pointer) {
	watcher := Watcher{
		Type: int(Type),
		State: int(state),
		Path: C.GoString((*C.char)(path)),
	}
	ch := (*chan Watcher)(ctx)
	(*ch) <- watcher
}

func GoStatCompletion2(rc C.int, vstat unsafe.Pointer, data unsafe.Pointer) {
	stat := (*C.struct_Stat)(vstat)
	ch := (*chan StatResult)(data)
	result := StatResult{
		rc : rc,
		stat : *stat,
	}
	(*ch) <-result
}

func GoDataCompletion2(
	rc C.int,
	value unsafe.Pointer,
	value_len C.int,
	stat, data unsafe.Pointer) {

	ch := (*chan DataResult)(data)
	result := DataResult{
		rc: rc,
		data: C.GoBytes(value, value_len),
		stat: *(*C.struct_Stat)(stat),
	}

	(*ch) <-result
}

type ZkID struct {
	id C.clientid_t
}

type ZHandle struct {
	handle *C.zhandle_t
}

/**
 * \brief create a new Zookeeper handle.
 *
 * The return value is the zookeeper handle.
 */
func NewZHandle(hosts string, recvTimeout int, id *ZkID) (h ZHandle, ok bool) {
	chosts := C.CString(hosts)
	defer C.free(unsafe.Pointer(chosts))

	handle, err := C.zookeeper_init(
		chosts, (C.watcher_fn)(C.my_global_watcher), C.int(recvTimeout), &id.id, nil, 0)

	if err != nil {
		ok = false
	} else {
		ok = true
		h = ZHandle{handle: handle}
	}
	return
}

/**
 * \brief get the state of the zookeeper connection.
 *
 * The return value will be one of the \ref State Consts.
 */
func (zh *ZHandle) GetState() int {
	return int(C.zoo_state(zh.handle))
}

/**
 * \brief checks the existence of a node in zookeeper.
 *
 */
func (zh *ZHandle) Exists(path string) StatResult {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res := make(chan StatResult, 1)
	rc,err := C.zoo_awexists(
		zh.handle,
		cpath,
		nil,
		nil,
		C.stat_completion_t(C.my_stat_completion),
		unsafe.Pointer(&res))

	var ret StatResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res
	}

	return ret
}

/**
 * \brief checks the existence of a node in zookeeper.
 *
 */
func (zh *ZHandle) ExistsW(path string) (StatResult, chan Watcher) {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res1 := make(chan StatResult, 1)
	res2 := make(chan Watcher, 1)

	rc,err := C.zoo_awexists(
		zh.handle,
		cpath,
		C.watcher_fn(C.my_watcher),
		unsafe.Pointer(&res2),
		C.stat_completion_t(C.my_stat_completion),
		unsafe.Pointer(&res1))

	var ret StatResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res1
	}

	return ret, res2
}

/**
 * \brief gets the data associated with a node.
 */
func (zh *ZHandle) Get(path string) DataResult {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res := make(chan DataResult, 1)
	rc,err := C.zoo_awget(
		zh.handle,
		cpath,
		nil,
		nil,
		C.data_completion_t(C.my_data_completion),
		unsafe.Pointer(&res))

	var ret DataResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res
	}

	return ret
}

/**
 * \brief gets the data associated with a node.
 */
func (zh *ZHandle) GetW(path string) (DataResult, chan Watcher) {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res1 := make(chan DataResult, 1)
	res2 := make(chan Watcher, 1)

	rc,err := C.zoo_awget(
		zh.handle,
		cpath,
		C.watcher_fn(C.my_watcher),
		unsafe.Pointer(&res2),
		C.data_completion_t(C.my_data_completion),
		unsafe.Pointer(&res1))

	var ret DataResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res1
	}

	return ret, res2
}

/**
 * \brief sets the data associated with a node.
 *
 * \param path the name of the node. Expressed as a file name with slashes
 * separating ancestors of the node.
 * \param buffer the buffer holding data to be written to the node.
 * \param version the expected version of the node. The function will fail if
 * the actual version of the node does not match the expected version. If -1 is
 * used the version check will not take place. * completion: If null,
 * the function will execute synchronously. Otherwise, the function will return
 * immediately and invoke the completion routine when the request completes.
 * \return ZOK on success or one of the following errcodes on failure:
 * ZBADARGUMENTS - invalid input parameters
 * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
 * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
 */
func (zh *ZHandle) Set(path string, buffer []byte, version int) StatResult {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	res := make(chan StatResult, 1)
	rc,err := C.zoo_aset(
		zh.handle,
		cpath,
		(*C.char)(unsafe.Pointer(&buffer[0])),
		C.int(len(buffer)),
		C.int(version),
		C.stat_completion_t(C.my_stat_completion),
		unsafe.Pointer(&res))

	var ret StatResult
	if err != nil {
		ret.rc = rc
	} else {
		ret = <-res
	}

	return ret
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package arrays

// Rearrange change order of given slice such that all elements
// less than an[i] appear first, followed by elements equal to
// an[i], followed by elements greater than an[i].
// The time complexity is O(n) and O(1) additional space is needed.
func Rearrange(an []int, i int) {
	v := an[i]
	p, q, r := 0, 0, len(an)-1
	// Loop invariant: elements less then the pivot an[0:p], elements equal to the pivot an[p:q],
	// unclassified an[q:r+1], elements greater then the pivot an[r+1:len(an)-1].
	// The time complexity is O(n) because on each iteration we decrease number of unclassified elements by 1.
	for q <= r {
		switch {
		case an[q] < v:
			an[q], an[p] = an[p], an[q]
			p++
			q++
		case an[q] > v:
			an[q], an[r] = an[r], an[q]
			r--
		case an[q] == v:
			q++
		}
	}
}
<commit_msg>Change formating of Loop Invariant in arrays.Rearange function<commit_after>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package arrays

// Rearrange change order of given slice such that all elements
// less than an[i] appear first, followed by elements equal to
// an[i], followed by elements greater than an[i].
// The time complexity is O(n) and O(1) additional space is needed.
func Rearrange(an []int, i int) {
	v := an[i]
	p, q, r := 0, 0, len(an)-1
	// Loop invariant:
	// elements less then the pivot an[0:p];
	// elements equal to the pivot an[p:q];
	// elements that are unclassified an[q:r+1];
	// elements greater then the pivot an[r+1:len(an)-1].
	// The time complexity is O(n) because on each iteration we decrease number of unclassified elements by 1.
	for q <= r {
		switch {
		case an[q] < v:
			an[q], an[p] = an[p], an[q]
			p++
			q++
		case an[q] > v:
			an[q], an[r] = an[r], an[q]
			r--
		case an[q] == v:
			q++
		}
	}
}
<|endoftext|>


<commit_before>package pushManager

import (
	"Go_Baidu_Push/config"
	"Go_Baidu_Push/util"
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"

	"strconv"
	"time"
)

var _pm *PushManager

func SharedPushManager() *PushManager {
	if _pm == nil {
		_pm = &PushManager{
			secretKey: config.SECRET_KEY,
			apiKey:    config.API_KEY,
		}
	}
	return _pm
}

type PushManager struct {
	secretKey string
	apiKey    string
}

func (p *PushManager) applyBaseParameters(parameters map[string]string) {
	parameters["apikey"] = p.apiKey
	parameters["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
}

func (p *PushManager) PushToAll(device_type, msg_type, msg, deploy_status string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/all"
	dic := make(map[string]string)
	dic["device_type"] = device_type
	dic["msg_type"] = msg_type
	dic["deploy_status"] = deploy_status
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) PushToSingle(device_type, channel_id, msg_type, msg, deploy_status string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/single_device"
	dic := make(map[string]string)
	dic["device_type"] = device_type
	dic["msg_type"] = msg_type
	dic["deploy_status"] = deploy_status
	dic["channel_id"] = channel_id
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) PushToTag(device_type, tag, msg_type, msg, deploy_status string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/tags"
	dic := make(map[string]string)
	dic["type"] = "1"
	dic["device_type"] = device_type
	dic["tag"] = tag
	dic["msg_type"] = msg_type
	dic["deploy_status"] = deploy_status
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) PushToBatchDevices(device_type, msg_type, msg, topicId string, channel_ids []string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/batch_device"
	dic := make(map[string]string)
	channels, err := json.Marshal(&channel_ids)
	if err != nil {
		return
	}
	dic["channel_ids"] = string(channels)
	dic["device_type"] = device_type
	dic["msg_type"] = msg_type
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) QueryMsgStatus(msgIds []string) {

}

func (p *PushManager) QueryTimerRecords(timerId, start, limit, rangeStart, rangeEnd string) {

}

func (p *PushManager) QueryTopicRecords(topicId, start, limit, rangeStart, rangeEnd string) {

}

func (p *PushManager) QueryTagDetails(tag string) {

}

func (p *PushManager) QueryTags(start, limit string) {

}

func (p *PushManager) CreateTag(tag string) {

}

func (p *PushManager) DeleteTag(tag string) {

}

func (p *PushManager) AddDevicesToTag(tag string, channelIds []string) {

}

func (p *PushManager) DeleteDevicesFromTag(tag string, channelIds []string) {

}

func (p *PushManager) QueryNumberOfDevicesInTag(tag string) {

}

func (p *PushManager) QueryTimerDetails(timerId string) {

}

func (p *PushManager) QueryTimerList(start, limit string) {

}

func (p *PushManager) CancelTimerTask(timerId string) {

}

func (p *PushManager) QueryTopicList(start, limit string) {

}

func (p *PushManager) QueryDeviceStatistic() {

}

func (p *PushManager) QueryTopicStatistic(topicId string) {

}

func postURL(targetURL string, dic map[string]string) (resp map[string]interface{}, err error) {
	form := url.Values{}
	for k, v := range dic {
		form.Set(k, v)
	}
	client := &http.Client{}
	req, err := http.NewRequest("POST", targetURL, bytes.NewBufferString(form.Encode()))
	if err != nil {
		log.Println(err.Error())
		return
	}
	req.Header.Add("User-Agent", config.USERAGENT)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
	req.Header.Add("Content-Length", strconv.Itoa(len(form.Encode())))

	response, err := client.Do(req)
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer response.Body.Close()
	bd, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Println(err.Error())
		return
	}
	log.Println(string(bd))
	err = json.Unmarshal(bd, &resp)
	if err != nil {
		log.Println(err.Error())
		return
	}
	log.Println(resp)
	if resp["error_code"] != nil {
		err = errors.New("Push failed")
	}
	return
}
<commit_msg>Query msg status<commit_after>package pushManager

import (
	"Go_Baidu_Push/config"
	"Go_Baidu_Push/util"
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"

	"strconv"
	"time"
)

var _pm *PushManager

func SharedPushManager() *PushManager {
	if _pm == nil {
		_pm = &PushManager{
			secretKey: config.SECRET_KEY,
			apiKey:    config.API_KEY,
		}
	}
	return _pm
}

type PushManager struct {
	secretKey string
	apiKey    string
}

func (p *PushManager) applyBaseParameters(parameters map[string]string) {
	parameters["apikey"] = p.apiKey
	parameters["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
}

func (p *PushManager) PushToAll(device_type, msg_type, msg, deploy_status string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/all"
	dic := make(map[string]string)
	dic["device_type"] = device_type
	dic["msg_type"] = msg_type
	dic["deploy_status"] = deploy_status
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) PushToSingle(device_type, channel_id, msg_type, msg, deploy_status string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/single_device"
	dic := make(map[string]string)
	dic["device_type"] = device_type
	dic["msg_type"] = msg_type
	dic["deploy_status"] = deploy_status
	dic["channel_id"] = channel_id
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) PushToTag(device_type, tag, msg_type, msg, deploy_status string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/tags"
	dic := make(map[string]string)
	dic["type"] = "1"
	dic["device_type"] = device_type
	dic["tag"] = tag
	dic["msg_type"] = msg_type
	dic["deploy_status"] = deploy_status
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) PushToBatchDevices(device_type, msg_type, msg, topicId string, channel_ids []string, parameters map[string]string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/push/batch_device"
	dic := make(map[string]string)
	channels, err := json.Marshal(&channel_ids)
	if err != nil {
		return
	}
	dic["channel_ids"] = string(channels)
	dic["device_type"] = device_type
	dic["msg_type"] = msg_type
	dic["msg"] = util.BuildMessage(msg, parameters, device_type)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) QueryMsgStatus(msgIds []string) (resp map[string]interface{}, err error) {
	targetURL := "http://api.tuisong.baidu.com/rest/3.0/report/query_msg_status"
	dic := make(map[string]string)
	ids, err := json.Marshal(&msgIds)
	if err != nil {
		return
	}
	dic["msg_id"] = string(ids)
	p.applyBaseParameters(dic)
	dic["sign"] = util.GenerateSignature("POST", targetURL, p.secretKey, dic)
	return postURL(targetURL, dic)
}

func (p *PushManager) QueryTimerRecords(timerId, start, limit, rangeStart, rangeEnd string) {

}

func (p *PushManager) QueryTopicRecords(topicId, start, limit, rangeStart, rangeEnd string) {

}

func (p *PushManager) QueryTagDetails(tag string) {

}

func (p *PushManager) QueryTags(start, limit string) {

}

func (p *PushManager) CreateTag(tag string) {

}

func (p *PushManager) DeleteTag(tag string) {

}

func (p *PushManager) AddDevicesToTag(tag string, channelIds []string) {

}

func (p *PushManager) DeleteDevicesFromTag(tag string, channelIds []string) {

}

func (p *PushManager) QueryNumberOfDevicesInTag(tag string) {

}

func (p *PushManager) QueryTimerDetails(timerId string) {

}

func (p *PushManager) QueryTimerList(start, limit string) {

}

func (p *PushManager) CancelTimerTask(timerId string) {

}

func (p *PushManager) QueryTopicList(start, limit string) {

}

func (p *PushManager) QueryDeviceStatistic() {

}

func (p *PushManager) QueryTopicStatistic(topicId string) {

}

func postURL(targetURL string, dic map[string]string) (resp map[string]interface{}, err error) {
	form := url.Values{}
	for k, v := range dic {
		form.Set(k, v)
	}
	client := &http.Client{}
	req, err := http.NewRequest("POST", targetURL, bytes.NewBufferString(form.Encode()))
	if err != nil {
		log.Println(err.Error())
		return
	}
	req.Header.Add("User-Agent", config.USERAGENT)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
	req.Header.Add("Content-Length", strconv.Itoa(len(form.Encode())))

	response, err := client.Do(req)
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer response.Body.Close()
	bd, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Println(err.Error())
		return
	}
	log.Println(string(bd))
	err = json.Unmarshal(bd, &resp)
	if err != nil {
		log.Println(err.Error())
		return
	}
	log.Println(resp)
	if resp["error_code"] != nil {
		err = errors.New("Push failed")
	}
	return
}
<|endoftext|>


<commit_before>package departure

import (
	"time"
	"fmt"
	"net/http"
	"encoding/json"
	"net/url"
	"strings"
)

type direction struct {
	Status string
	Routes []struct {
		Legs []struct {
			Steps [] struct {
				TransitDetails struct {
					DepartureTime struct {
						Value int64
					} `json:"departure_time"`
					Line struct {
						ShortName string `json:"short_name"`
					}
				} `json:"transit_details"`
				TravelMode string `json:"travel_mode"`
			}
		}
	}
}

func (d *direction) getDepartureTime(lineNames []string, isWalk bool) (time.Time, error) {
	if d.Status != "OK" {
		return time.Time{}, fmt.Errorf("direction status was not OK but %s", d.Status)
	}

	for _, route := range d.Routes {
		if len(route.Legs) == 1 {
			transitSteps := 0
			hasLine := false
			var depTimestamp int64
			for _, step := range route.Legs[0].Steps {
				if !isWalk && step.TravelMode == "WALKING" {
					break
				}

				if step.TravelMode == "TRANSIT" {
					transitSteps++
					if stringSliceContains(lineNames, step.TransitDetails.Line.ShortName) {
						hasLine = true
						depTimestamp = step.TransitDetails.DepartureTime.Value
					}
				}
			}

			if hasLine && transitSteps == 1 {
				depTime := time.Unix(depTimestamp, 0)

				return depTime, nil
			}
		}
	}

	return time.Time{}, fmt.Errorf("No route found for lines %q", strings.Join(lineNames, "|"))
}

func stringSliceContains(slice []string, subject string) bool {
	for _, s := range slice {
		if s == subject {
			return true
		}
	}
	return false
}

func GetDepartureTime(origin, destination, apiKey, transitMode string, lineNames []string, desiredDepTime time.Time, isWalk bool) (time.Time, error) {
	query := createQuery(origin, destination, apiKey, transitMode, desiredDepTime)

	var direction direction
	getJson(query, &direction)

	depTime, err := direction.getDepartureTime(lineNames, isWalk)

	return depTime, err
}

func createQuery(origin, destination, apiKey, transitMode string, desiredDepTime time.Time) string {
	baseUrl := "https://maps.googleapis.com/maps/api/directions/json"
	query := fmt.Sprintf(
		"%s?departure_time=%d&origin=%s&destination=%s&key=%s&mode=transit&transit_mode=%s&language=en&alternatives=true",
		baseUrl,
		desiredDepTime.Unix(),
		url.QueryEscape(origin),
		url.QueryEscape(destination),
		url.QueryEscape(apiKey),
		url.QueryEscape(transitMode),
	)

	return query
}

func getJson(url string, target interface{}) error {
	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	return json.NewDecoder(r.Body).Decode(target)
}
<commit_msg>Refactor createQuery<commit_after>package departure

import (
	"time"
	"fmt"
	"net/http"
	"encoding/json"
	"net/url"
	"strings"
	"strconv"
)

type direction struct {
	Status string
	Routes []struct {
		Legs []struct {
			Steps [] struct {
				TransitDetails struct {
					DepartureTime struct {
						Value int64
					} `json:"departure_time"`
					Line struct {
						ShortName string `json:"short_name"`
					}
				} `json:"transit_details"`
				TravelMode string `json:"travel_mode"`
			}
		}
	}
}

func (d *direction) getDepartureTime(lineNames []string, isWalk bool) (time.Time, error) {
	if d.Status != "OK" {
		return time.Time{}, fmt.Errorf("direction status was not OK but %s", d.Status)
	}

	for _, route := range d.Routes {
		if len(route.Legs) == 1 {
			transitSteps := 0
			hasLine := false
			var depTimestamp int64
			for _, step := range route.Legs[0].Steps {
				if !isWalk && step.TravelMode == "WALKING" {
					break
				}

				if step.TravelMode == "TRANSIT" {
					transitSteps++
					if stringSliceContains(lineNames, step.TransitDetails.Line.ShortName) {
						hasLine = true
						depTimestamp = step.TransitDetails.DepartureTime.Value
					}
				}
			}

			if hasLine && transitSteps == 1 {
				depTime := time.Unix(depTimestamp, 0)

				return depTime, nil
			}
		}
	}

	return time.Time{}, fmt.Errorf("No route found for lines %q", strings.Join(lineNames, "|"))
}

func stringSliceContains(slice []string, subject string) bool {
	for _, s := range slice {
		if s == subject {
			return true
		}
	}
	return false
}

func GetDepartureTime(origin, destination, apiKey, transitMode string, lineNames []string, desiredDepTime time.Time, isWalk bool) (time.Time, error) {
	query := createQuery(origin, destination, apiKey, transitMode, desiredDepTime)

	var direction direction
	getJson(query, &direction)

	depTime, err := direction.getDepartureTime(lineNames, isWalk)

	return depTime, err
}

func createQuery(origin, destination, apiKey, transitMode string, desiredDepTime time.Time) string {
	query, _ := url.Parse("https://maps.googleapis.com/maps/api/directions/json")

	params := url.Values{}
	params.Set("departure_time", strconv.FormatInt(desiredDepTime.Unix(), 10))
	params.Set("origin", origin)
	params.Set("destination", destination)
	params.Set("key", apiKey)
	params.Set("mode", "transit")
	params.Set("transit_mode", transitMode)
	params.Set("language", "en")
	params.Set("alternatives", "true")

	query.RawQuery = params.Encode()

	return query.String()
}

func getJson(url string, target interface{}) error {
	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	return json.NewDecoder(r.Body).Decode(target)
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Deep equality test via reflection

package jsonschema

import (
	"encoding/json"
	"reflect"
	"strings"
)

// NEW FOR JSONSCHEMA
var stringType = reflect.TypeOf("")
var boolType = reflect.TypeOf(false)
var jsonNumberType = reflect.TypeOf(json.Number(""))

// During deepValueEqual, must keep track of checks that are
// in progress.  The comparison algorithm assumes that all
// checks in progress are true when it reencounters them.
// Visited comparisons are stored in a map indexed by visit.
type visit struct {
	a1  uintptr
	a2  uintptr
	typ reflect.Type
}

// Tests for deep equality using reflected types. The map argument tracks
// comparisons that have already been seen, which allows short circuiting on
// recursive types.
func deepValueEqual(v1, v2 reflect.Value, visited map[visit]bool, depth int) bool {
	if !v1.IsValid() || !v2.IsValid() {
		return v1.IsValid() == v2.IsValid()
	}

	// BEGIN NEW FOR JSONSCHEMA
	//
	// Go's deepValueEqual uses this line at the end of the v1.Kind() switch below to compare simple types:
	//
	//     return valueInterface(v1, false) == valueInterface(v2, false)
	//
	// this isn't an option for us because valueInterface isn't exported. We need to implement our own
	// comparison anyway because we want to make some type conversions (e.g. from json.Number to int64)
	// before testing for equality.
	//
	// So instead we handle simple types with our own type switch here before the v1.Kind() switch is run.
	//
	//
	// NOTE: We use Type() for the switch here instead of Kind() like in the v1.Kind() switch below,
	// because reflect.Kind doesn't distinguish between json.Number and string.
	//
	// NOTE: We use the switch on v2 here instead of v1 like the switch below. Since this package controls
	// the deserialization of schemas we know that if v2 is a number it will always be a json.Number.
	// We can't say the same for v1.
	//
	// TODO: We need to add tests where v2 is an integer and v1 is a float. Then we need code to cover
	// that situation.
	b1 := v1.Interface()
	b2 := v2.Interface()
	switch v2.Type() {
	case stringType:
		c1, ok1 := b1.(string)
		c2, ok2 := b2.(string)
		if ok1 && ok2 {
			return c1 == c2
		} else {
			return false
		}
	case boolType:
		c1, ok1 := b1.(bool)
		c2, ok2 := b2.(bool)
		if ok1 && ok2 {
			return c1 == c2
		} else {
			return false
		}
	case jsonNumberType:
		norm, err := normalizeNumber(b1)
		if err != nil {
			return false
		}
		jnum, ok := b2.(json.Number)
		if !ok {
			return false
		}
		if strings.Contains(jnum.String(), ".") {
			c2, err := jnum.Float64()
			if err != nil {
				return false
			}
			c1, ok := norm.(float64)
			if !ok {
				return false
			}
			return c1 == c2
		} else {
			c2, err := jnum.Int64()
			if err != nil {
				return false
			}
			c1, ok := norm.(int64)
			if !ok {
				return false
			}
			return c1 == c2
		}
	}
	// END NEW FOR JSONSCHEMA

	if v1.Type() != v2.Type() {
		return false
	}

	// if depth > 10 { panic("deepValueEqual") }	// for debugging
	hard := func(k reflect.Kind) bool {
		switch k {
		case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct:
			return true
		}
		return false
	}

	if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
		addr1 := v1.UnsafeAddr()
		addr2 := v2.UnsafeAddr()
		if addr1 > addr2 {
			// Canonicalize order to reduce number of entries in visited.
			addr1, addr2 = addr2, addr1
		}

		// Short circuit if references are identical ...
		if addr1 == addr2 {
			return true
		}

		// ... or already seen
		typ := v1.Type()
		v := visit{addr1, addr2, typ}
		if visited[v] {
			return true
		}

		// Remember for later.
		visited[v] = true
	}

	switch v1.Kind() {
	case reflect.Array:
		if v1.Len() != v2.Len() {
			return false
		}
		for i := 0; i < v1.Len(); i++ {
			if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Slice:
		if v1.IsNil() != v2.IsNil() {
			return false
		}
		if v1.Len() != v2.Len() {
			return false
		}
		if v1.Pointer() == v2.Pointer() {
			return true
		}
		for i := 0; i < v1.Len(); i++ {
			if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Interface:
		if v1.IsNil() || v2.IsNil() {
			return v1.IsNil() == v2.IsNil()
		}
		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
	case reflect.Ptr:
		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
	case reflect.Struct:
		for i, n := 0, v1.NumField(); i < n; i++ {
			if !deepValueEqual(v1.Field(i), v2.Field(i), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Map:
		if v1.IsNil() != v2.IsNil() {
			return false
		}
		if v1.Len() != v2.Len() {
			return false
		}
		if v1.Pointer() == v2.Pointer() {
			return true
		}
		for _, k := range v1.MapKeys() {
			if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Func:
		if v1.IsNil() && v2.IsNil() {
			return true
		}
		// Can't do better than this:
		return false
	default:

		// REMOVED FOR JSONSCHEMA
		//
		// // Normal equality suffices
		// return valueInterface(v1, false) == valueInterface(v2, false)

		// ADDED FOR JSONSCHEMA
		return false
	}
}

// DeepEqual tests for deep equality. It uses normal == equality where
// possible but will scan elements of arrays, slices, maps, and fields of
// structs. In maps, keys are compared with == but elements use deep
// equality. DeepEqual correctly handles recursive types. Functions are equal
// only if they are both nil.
// An empty slice is not equal to a nil slice.
func DeepEqual(a1, a2 interface{}) bool {
	if a1 == nil || a2 == nil {
		return a1 == a2
	}
	v1 := reflect.ValueOf(a1)
	v2 := reflect.ValueOf(a2)

	// REMOVED FOR JSONSCHEMA
	//
	// if v1.Type() != v2.Type() {
	// 	return false
	// }

	return deepValueEqual(v1, v2, make(map[visit]bool), 0)
}
<commit_msg>Style fix -- indent exceptional occurances.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Deep equality test via reflection

package jsonschema

import (
	"encoding/json"
	"reflect"
	"strings"
)

// NEW FOR JSONSCHEMA
var stringType = reflect.TypeOf("")
var boolType = reflect.TypeOf(false)
var jsonNumberType = reflect.TypeOf(json.Number(""))

// During deepValueEqual, must keep track of checks that are
// in progress.  The comparison algorithm assumes that all
// checks in progress are true when it reencounters them.
// Visited comparisons are stored in a map indexed by visit.
type visit struct {
	a1  uintptr
	a2  uintptr
	typ reflect.Type
}

// Tests for deep equality using reflected types. The map argument tracks
// comparisons that have already been seen, which allows short circuiting on
// recursive types.
func deepValueEqual(v1, v2 reflect.Value, visited map[visit]bool, depth int) bool {
	if !v1.IsValid() || !v2.IsValid() {
		return v1.IsValid() == v2.IsValid()
	}

	// BEGIN NEW FOR JSONSCHEMA
	//
	// Go's deepValueEqual uses this line at the end of the v1.Kind() switch below to compare simple types:
	//
	//     return valueInterface(v1, false) == valueInterface(v2, false)
	//
	// this isn't an option for us because valueInterface isn't exported. We need to implement our own
	// comparison anyway because we want to make some type conversions (e.g. from json.Number to int64)
	// before testing for equality.
	//
	// So instead we handle simple types with our own type switch here before the v1.Kind() switch is run.
	//
	//
	// NOTE: We use Type() for the switch here instead of Kind() like in the v1.Kind() switch below,
	// because reflect.Kind doesn't distinguish between json.Number and string.
	//
	// NOTE: We use the switch on v2 here instead of v1 like the switch below. Since this package controls
	// the deserialization of schemas we know that if v2 is a number it will always be a json.Number.
	// We can't say the same for v1.
	//
	// TODO: We need to add tests where v2 is an integer and v1 is a float. Then we need code to cover
	// that situation.
	b1 := v1.Interface()
	b2 := v2.Interface()
	switch v2.Type() {
	case stringType:
		c1, ok1 := b1.(string)
		c2, ok2 := b2.(string)
		if !ok1 || !ok2 {
			return false
		}
		return c1 == c2
	case boolType:
		c1, ok1 := b1.(bool)
		c2, ok2 := b2.(bool)
		if !ok1 || !ok2 {
			return false
		}
		return c1 == c2
	case jsonNumberType:
		norm, err := normalizeNumber(b1)
		if err != nil {
			return false
		}
		jnum, ok := b2.(json.Number)
		if !ok {
			return false
		}
		if strings.Contains(jnum.String(), ".") {
			c2, err := jnum.Float64()
			if err != nil {
				return false
			}
			c1, ok := norm.(float64)
			if !ok {
				return false
			}
			return c1 == c2
		} else {
			c2, err := jnum.Int64()
			if err != nil {
				return false
			}
			c1, ok := norm.(int64)
			if !ok {
				return false
			}
			return c1 == c2
		}
	}
	// END NEW FOR JSONSCHEMA

	if v1.Type() != v2.Type() {
		return false
	}

	// if depth > 10 { panic("deepValueEqual") }	// for debugging
	hard := func(k reflect.Kind) bool {
		switch k {
		case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct:
			return true
		}
		return false
	}

	if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
		addr1 := v1.UnsafeAddr()
		addr2 := v2.UnsafeAddr()
		if addr1 > addr2 {
			// Canonicalize order to reduce number of entries in visited.
			addr1, addr2 = addr2, addr1
		}

		// Short circuit if references are identical ...
		if addr1 == addr2 {
			return true
		}

		// ... or already seen
		typ := v1.Type()
		v := visit{addr1, addr2, typ}
		if visited[v] {
			return true
		}

		// Remember for later.
		visited[v] = true
	}

	switch v1.Kind() {
	case reflect.Array:
		if v1.Len() != v2.Len() {
			return false
		}
		for i := 0; i < v1.Len(); i++ {
			if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Slice:
		if v1.IsNil() != v2.IsNil() {
			return false
		}
		if v1.Len() != v2.Len() {
			return false
		}
		if v1.Pointer() == v2.Pointer() {
			return true
		}
		for i := 0; i < v1.Len(); i++ {
			if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Interface:
		if v1.IsNil() || v2.IsNil() {
			return v1.IsNil() == v2.IsNil()
		}
		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
	case reflect.Ptr:
		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
	case reflect.Struct:
		for i, n := 0, v1.NumField(); i < n; i++ {
			if !deepValueEqual(v1.Field(i), v2.Field(i), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Map:
		if v1.IsNil() != v2.IsNil() {
			return false
		}
		if v1.Len() != v2.Len() {
			return false
		}
		if v1.Pointer() == v2.Pointer() {
			return true
		}
		for _, k := range v1.MapKeys() {
			if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
				return false
			}
		}
		return true
	case reflect.Func:
		if v1.IsNil() && v2.IsNil() {
			return true
		}
		// Can't do better than this:
		return false
	default:

		// REMOVED FOR JSONSCHEMA
		//
		// // Normal equality suffices
		// return valueInterface(v1, false) == valueInterface(v2, false)

		// ADDED FOR JSONSCHEMA
		return false
	}
}

// DeepEqual tests for deep equality. It uses normal == equality where
// possible but will scan elements of arrays, slices, maps, and fields of
// structs. In maps, keys are compared with == but elements use deep
// equality. DeepEqual correctly handles recursive types. Functions are equal
// only if they are both nil.
// An empty slice is not equal to a nil slice.
func DeepEqual(a1, a2 interface{}) bool {
	if a1 == nil || a2 == nil {
		return a1 == a2
	}
	v1 := reflect.ValueOf(a1)
	v2 := reflect.ValueOf(a2)

	// REMOVED FOR JSONSCHEMA
	//
	// if v1.Type() != v2.Type() {
	// 	return false
	// }

	return deepValueEqual(v1, v2, make(map[visit]bool), 0)
}
<|endoftext|>


<commit_before>package glfw

/*
// Windows Build Tags
// ----------------
// GLFW Options:
#cgo windows CFLAGS: -D_GLFW_WIN32 -Iglfw/deps/mingw

// Linker Options:
#cgo windows LDFLAGS: -lopengl32 -lgdi32

// Darwin Build Tags
// ----------------
// GLFW Options:
#cgo darwin CFLAGS: -D_GLFW_COCOA -Wno-deprecated-declarations

// Linker Options:
#cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo

// Linux Build Tags
// ----------------
// GLFW Options:
#cgo linux,!wayland CFLAGS: -D_GLFW_X11 -D_GNU_SOURCE
#cgo linux,wayland CFLAGS: -D_GLFW_WAYLAND -D_GNU_SOURCE

// Linker Options:
#cgo linux,!gles1,!gles2,!gles3,!vulkan LDFLAGS: -lGL
#cgo linux,gles1 LDFLAGS: -lGLESv1
#cgo linux,gles2 LDFLAGS: -lGLESv2
#cgo linux,gles3 LDFLAGS: -lGLESv3
#cgo linux,vulkan LDFLAGS: -lvulkan
#cgo linux,!wayland LDFLAGS: -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lm -lXinerama -ldl -lrt
#cgo linux,wayland LDFLAGS: -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon -lm -ldl -lrt

// FreeBSD Build Tags
// ----------------
// GLFW Options:
#cgo freebsd pkg-config: glfw3
#cgo freebsd CFLAGS: -D_GLFW_HAS_DLOPEN
#cgo freebsd,!wayland CFLAGS: -D_GLFW_X11 -D_GLFW_HAS_GLXGETPROCADDRESSARB
#cgo freebsd,wayland CFLAGS: -D_GLFW_WAYLAND

// Linker Options:
#cgo freebsd,!wayland LDFLAGS: -lm -lGL -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lXinerama
#cgo freebsd,wayland LDFLAGS: -lm -lGL -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
*/
import "C"
<commit_msg>add gles2 tag to support using gles2 on windows<commit_after>package glfw

/*
// Windows Build Tags
// ----------------
// GLFW Options:
#cgo windows CFLAGS: -D_GLFW_WIN32 -Iglfw/deps/mingw

// Linker Options:
#cgo windows LDFLAGS: -lgdi32

#cgo !gles2,windows LDFLAGS: -lopengl32
#cgo gles2,windows LDFLAGS: -lGLESv2

// Darwin Build Tags
// ----------------
// GLFW Options:
#cgo darwin CFLAGS: -D_GLFW_COCOA -Wno-deprecated-declarations

// Linker Options:
#cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo

// Linux Build Tags
// ----------------
// GLFW Options:
#cgo linux,!wayland CFLAGS: -D_GLFW_X11 -D_GNU_SOURCE
#cgo linux,wayland CFLAGS: -D_GLFW_WAYLAND -D_GNU_SOURCE

// Linker Options:
#cgo linux,!gles1,!gles2,!gles3,!vulkan LDFLAGS: -lGL
#cgo linux,gles1 LDFLAGS: -lGLESv1
#cgo linux,gles2 LDFLAGS: -lGLESv2
#cgo linux,gles3 LDFLAGS: -lGLESv3
#cgo linux,vulkan LDFLAGS: -lvulkan
#cgo linux,!wayland LDFLAGS: -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lm -lXinerama -ldl -lrt
#cgo linux,wayland LDFLAGS: -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon -lm -ldl -lrt

// FreeBSD Build Tags
// ----------------
// GLFW Options:
#cgo freebsd pkg-config: glfw3
#cgo freebsd CFLAGS: -D_GLFW_HAS_DLOPEN
#cgo freebsd,!wayland CFLAGS: -D_GLFW_X11 -D_GLFW_HAS_GLXGETPROCADDRESSARB
#cgo freebsd,wayland CFLAGS: -D_GLFW_WAYLAND

// Linker Options:
#cgo freebsd,!wayland LDFLAGS: -lm -lGL -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lXinerama
#cgo freebsd,wayland LDFLAGS: -lm -lGL -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
*/
import "C"
<|endoftext|>