<commit_before>package rainsd

import (
	"crypto/ecdsa"
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/json"
	"errors"
	"io/ioutil"
	"math/big"
	"net"
	"rains/rainslib"

	"rains/utils/cache"

	log "github.com/inconshreveable/log15"
	"golang.org/x/crypto/ed25519"
)

const (
	configPath = "config/server.conf"
)

//InitServer initializes the server
func InitServer() error {
	h := log.CallerFileHandler(log.StdoutHandler)
	log.Root().SetHandler(h)
	loadConfig()
	if err := loadCert(); err != nil {
		return err
	}
	if err := initSwitchboard(); err != nil {
		return err
	}
	if err := initInbox(); err != nil {
		return err
	}
	if err := initVerify(); err != nil {
		return err
	}
	if err := initEngine(); err != nil {
		return err
	}

	return nil
}

//LoadConfig loads and stores server configuration
func loadConfig() {
	file, err := ioutil.ReadFile(configPath)
	if err != nil {
		log.Warn("Could not open config file...", "path", configPath, "error", err)
	}
	if err = json.Unmarshal(file, &Config); err != nil {
		log.Warn("Could not unmarshal json format of config")
	}
}

func loadCert() error {
	roots = x509.NewCertPool()
	file, err := ioutil.ReadFile(Config.CertificateFile)
	if err != nil {
		log.Error("error", err)
		return err
	}
	ok := roots.AppendCertsFromPEM(file)
	if !ok {
		log.Error("failed to parse root certificate")
		return errors.New("failed to parse root certificate")
	}
	return nil
}

//CreateNotificationMsg creates a notification messages
func CreateNotificationMsg(token rainslib.Token, notificationType rainslib.NotificationType, data string) ([]byte, error) {
	content := []rainslib.MessageSection{&rainslib.NotificationSection{Type: rainslib.MsgTooLarge, Token: token, Data: data}}
	msg := rainslib.RainsMessage{Token: rainslib.GenerateToken(), Content: content}
	return msgParser.ParseRainsMsg(msg)
}

//SignData returns a signature of the input data signed with the specified signing algorithm and the given private key.
func SignData(algoType rainslib.SignatureAlgorithmType, privateKey interface{}, data []byte) interface{} {
	switch algoType {
	case rainslib.Ed25519:
		if pkey, ok := privateKey.(ed25519.PrivateKey); ok {
			return ed25519.Sign(pkey, data)
		}
		log.Warn("Could not cast key to ed25519.PrivateKey", "privateKey", privateKey)
	case rainslib.Ed448:
		log.Warn("Ed448 not yet Supported!")
	case rainslib.Ecdsa256:
		if pkey, ok := privateKey.(*ecdsa.PrivateKey); ok {
			hash := sha256.Sum256(data)
			return signEcdsa(pkey, data, hash[:])
		}
		log.Warn("Could not cast key to ecdsa.PrivateKey", "privateKey", privateKey)
	case rainslib.Ecdsa384:
		if pkey, ok := privateKey.(*ecdsa.PrivateKey); ok {
			hash := sha512.Sum384(data)
			return signEcdsa(pkey, data, hash[:])
		}
		log.Warn("Could not cast key to ecdsa.PrivateKey", "privateKey", privateKey)
	default:
		log.Warn("Signature algorithm type not supported", "type", algoType)
	}
	return nil
}

func signEcdsa(privateKey *ecdsa.PrivateKey, data, hash []byte) interface{} {
	r, s, err := ecdsa.Sign(PRG{}, privateKey, hash)
	if err != nil {
		log.Warn("Could not sign data with Ecdsa256", "error", err)
	}
	return []*big.Int{r, s}
}

//VerifySignature returns true if the provided signature with the public key matches the data.
func VerifySignature(algoType rainslib.SignatureAlgorithmType, publicKey interface{}, data []byte, signature interface{}) bool {
	switch algoType {
	case rainslib.Ed25519:
		if pkey, ok := publicKey.(ed25519.PublicKey); ok {
			return ed25519.Verify(pkey, data, signature.([]byte))
		}
		log.Warn("Could not cast key to ed25519.PublicKey", "publicKey", publicKey)
	case rainslib.Ed448:
		log.Warn("Ed448 not yet Supported!")
	case rainslib.Ecdsa256:
		if pkey, ok := publicKey.(*ecdsa.PublicKey); ok {
			if sig, ok := signature.([]*big.Int); ok && len(sig) == 2 {
				hash := sha256.Sum256(data)
				return ecdsa.Verify(pkey, hash[:], sig[0], sig[1])
			}
			log.Warn("Could not cast signature ", "signature", signature)
			return false
		}
		log.Warn("Could not cast key to ecdsa.PublicKey", "publicKey", publicKey)
	case rainslib.Ecdsa384:
		if pkey, ok := publicKey.(*ecdsa.PublicKey); ok {
			if sig, ok := signature.([]*big.Int); ok && len(sig) == 2 {
				hash := sha512.Sum384(data)
				return ecdsa.Verify(pkey, hash[:], sig[0], sig[1])
			}
			log.Warn("Could not cast signature ", "signature", signature)
			return false
		}
		log.Warn("Could not cast key to ecdsa.PublicKey", "publicKey", publicKey)
	default:
		log.Warn("Signature algorithm type not supported", "type", algoType)
	}
	return false
}

func createConnectionCache() (connectionCache, error) {
	c, err := cache.NewWithEvict(func(value interface{}, key ...string) {
		if value, ok := value.(net.Conn); ok {
			value.Close()
		}
	}, int(Config.MaxConnections), "noAnyContext")
	if err != nil {
		return nil, err
	}
	return connectionCacheImpl{cache: c}, nil
}

func createCapabilityCache() (capabilityCache, error) {
	hc, err := cache.New(int(Config.CapabilitiesCacheSize), "noAnyContext")
	if err != nil {
		return nil, err
	}
	//FIXME CFE remove this after we can do it in the Add method of the cache
	hc.Add([]Capability{TLSOverTCP}, false, "", "e5365a09be554ae55b855f15264dbc837b04f5831daeb321359e18cdabab5745")
	hc.Add([]Capability{NoCapability}, false, "", "76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71")
	cc, err := cache.New(int(Config.PeerToCapCacheSize), "noAnyContext")
	if err != nil {
		return nil, err
	}
	return capabilityCacheImpl{hashToCap: hc, connInfoToCap: cc}, nil
}
<commit_msg>resolve merge conflict<commit_after>package rainsd

import (
	"crypto/ecdsa"
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/json"
	"errors"
	"io/ioutil"
	"math/big"
	"net"
	"rains/rainslib"
	"rains/utils/cache"

	log "github.com/inconshreveable/log15"
	"golang.org/x/crypto/ed25519"
)

const (
	configPath = "config/server.conf"
)

//InitServer initializes the server
func InitServer() error {
	h := log.CallerFileHandler(log.StdoutHandler)
	log.Root().SetHandler(h)
	loadConfig()
	if err := loadCert(); err != nil {
		return err
	}
	if err := initSwitchboard(); err != nil {
		return err
	}
	if err := initInbox(); err != nil {
		return err
	}
	if err := initVerify(); err != nil {
		return err
	}
	if err := initEngine(); err != nil {
		return err
	}

	return nil
}

//LoadConfig loads and stores server configuration
func loadConfig() {
	file, err := ioutil.ReadFile(configPath)
	if err != nil {
		log.Warn("Could not open config file...", "path", configPath, "error", err)
	}
	if err = json.Unmarshal(file, &Config); err != nil {
		log.Warn("Could not unmarshal json format of config")
	}
}

func loadCert() error {
	roots = x509.NewCertPool()
	file, err := ioutil.ReadFile(Config.CertificateFile)
	if err != nil {
		log.Error("error", err)
		return err
	}
	ok := roots.AppendCertsFromPEM(file)
	if !ok {
		log.Error("failed to parse root certificate")
		return errors.New("failed to parse root certificate")
	}
	return nil
}

//CreateNotificationMsg creates a notification messages
func CreateNotificationMsg(token rainslib.Token, notificationType rainslib.NotificationType, data string) ([]byte, error) {
	content := []rainslib.MessageSection{&rainslib.NotificationSection{Type: rainslib.MsgTooLarge, Token: token, Data: data}}
	msg := rainslib.RainsMessage{Token: rainslib.GenerateToken(), Content: content}
	return msgParser.ParseRainsMsg(msg)
}

//SignData returns a signature of the input data signed with the specified signing algorithm and the given private key.
func SignData(algoType rainslib.SignatureAlgorithmType, privateKey interface{}, data []byte) interface{} {
	switch algoType {
	case rainslib.Ed25519:
		if pkey, ok := privateKey.(ed25519.PrivateKey); ok {
			return ed25519.Sign(pkey, data)
		}
		log.Warn("Could not cast key to ed25519.PrivateKey", "privateKey", privateKey)
	case rainslib.Ed448:
		log.Warn("Ed448 not yet Supported!")
	case rainslib.Ecdsa256:
		if pkey, ok := privateKey.(*ecdsa.PrivateKey); ok {
			hash := sha256.Sum256(data)
			return signEcdsa(pkey, data, hash[:])
		}
		log.Warn("Could not cast key to ecdsa.PrivateKey", "privateKey", privateKey)
	case rainslib.Ecdsa384:
		if pkey, ok := privateKey.(*ecdsa.PrivateKey); ok {
			hash := sha512.Sum384(data)
			return signEcdsa(pkey, data, hash[:])
		}
		log.Warn("Could not cast key to ecdsa.PrivateKey", "privateKey", privateKey)
	default:
		log.Warn("Signature algorithm type not supported", "type", algoType)
	}
	return nil
}

func signEcdsa(privateKey *ecdsa.PrivateKey, data, hash []byte) interface{} {
	r, s, err := ecdsa.Sign(PRG{}, privateKey, hash)
	if err != nil {
		log.Warn("Could not sign data with Ecdsa256", "error", err)
	}
	return []*big.Int{r, s}
}

//VerifySignature returns true if the provided signature with the public key matches the data.
func VerifySignature(algoType rainslib.SignatureAlgorithmType, publicKey interface{}, data []byte, signature interface{}) bool {
	switch algoType {
	case rainslib.Ed25519:
		if pkey, ok := publicKey.(ed25519.PublicKey); ok {
			return ed25519.Verify(pkey, data, signature.([]byte))
		}
		log.Warn("Could not cast key to ed25519.PublicKey", "publicKey", publicKey)
	case rainslib.Ed448:
		log.Warn("Ed448 not yet Supported!")
	case rainslib.Ecdsa256:
		if pkey, ok := publicKey.(*ecdsa.PublicKey); ok {
			if sig, ok := signature.([]*big.Int); ok && len(sig) == 2 {
				hash := sha256.Sum256(data)
				return ecdsa.Verify(pkey, hash[:], sig[0], sig[1])
			}
			log.Warn("Could not cast signature ", "signature", signature)
			return false
		}
		log.Warn("Could not cast key to ecdsa.PublicKey", "publicKey", publicKey)
	case rainslib.Ecdsa384:
		if pkey, ok := publicKey.(*ecdsa.PublicKey); ok {
			if sig, ok := signature.([]*big.Int); ok && len(sig) == 2 {
				hash := sha512.Sum384(data)
				return ecdsa.Verify(pkey, hash[:], sig[0], sig[1])
			}
			log.Warn("Could not cast signature ", "signature", signature)
			return false
		}
		log.Warn("Could not cast key to ecdsa.PublicKey", "publicKey", publicKey)
	default:
		log.Warn("Signature algorithm type not supported", "type", algoType)
	}
	return false
}

func createConnectionCache() (connectionCache, error) {
	c, err := cache.NewWithEvict(func(value interface{}, key ...string) {
		if value, ok := value.(net.Conn); ok {
			value.Close()
		}
	}, int(Config.MaxConnections), "noAnyContext")
	if err != nil {
		return nil, err
	}
	return connectionCacheImpl{cache: c}, nil
}

func createCapabilityCache() (capabilityCache, error) {
	hc, err := cache.New(int(Config.CapabilitiesCacheSize), "noAnyContext")
	if err != nil {
		return nil, err
	}
	//FIXME CFE remove this after we can do it in the Add method of the cache
	hc.Add([]Capability{TLSOverTCP}, false, "", "e5365a09be554ae55b855f15264dbc837b04f5831daeb321359e18cdabab5745")
	hc.Add([]Capability{NoCapability}, false, "", "76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71")
	cc, err := cache.New(int(Config.PeerToCapCacheSize), "noAnyContext")
	if err != nil {
		return nil, err
	}
	return capabilityCacheImpl{hashToCap: hc, connInfoToCap: cc}, nil
}
<|endoftext|>


<commit_before>package paillier

import (
	"crypto/rand"
	"math/big"
	"reflect"
	"testing"
)

func TestLCM(t *testing.T) {
	a := big.NewInt(1350)
	b := big.NewInt(141075)
	expected := big.NewInt(282150)

	if !reflect.DeepEqual(expected, LCM(a, b)) {
		t.Fail()
	}
}

func TestL(t *testing.T) {
	u := big.NewInt(21)
	n := big.NewInt(3)
	exp := big.NewInt(6)
	if !reflect.DeepEqual(exp, L(u, n)) {
		t.Error("L function is not good")
	}
}

func TestComputeMu(t *testing.T) {
	p := big.NewInt(13)
	q := big.NewInt(11)

	lambda := computeLamda(p, q)
	g := big.NewInt(5000)
	n := new(big.Int).Mul(p, q)

	exp := big.NewInt(3)
	if !reflect.DeepEqual(computeMu(g, lambda, n), exp) {
		t.Error("mu is not well computed")
	}
}

func TestEncryptDecryptSmall(t *testing.T) {
	p := big.NewInt(13)
	q := big.NewInt(11)
	for i := 1; i < 10; i++ {
		privateKey := CreatePrivateKey(p, q)

		inicialValue := big.NewInt(100)
		cypher, err := privateKey.Encrypt(inicialValue, rand.Reader)
		if err != nil {
			t.Error(err)
		}
		returnedValue := privateKey.Decrypt(cypher)
		if !reflect.DeepEqual(inicialValue, returnedValue) {
			t.Error("wrond decryption ", returnedValue, " is not ", inicialValue)
		}
	}

}

func TestAddCypher(t *testing.T) {
	privateKey := CreatePrivateKey(big.NewInt(13), big.NewInt(11))
	cypher1, _ := privateKey.Encrypt(big.NewInt(12), rand.Reader)
	cypher2, _ := privateKey.Encrypt(big.NewInt(13), rand.Reader)
	cypher3 := privateKey.Add(cypher1, cypher2)
	m := privateKey.Decrypt(cypher3)
	if !reflect.DeepEqual(m, big.NewInt(25)) {
		t.Error(m)
	}
}
<commit_msg>Added test for Lambda parameter computation<commit_after>package paillier

import (
	"crypto/rand"
	"math/big"
	"reflect"
	"testing"
)

func TestLCM(t *testing.T) {
	a := big.NewInt(1350)
	b := big.NewInt(141075)
	expected := big.NewInt(282150)

	if !reflect.DeepEqual(expected, LCM(a, b)) {
		t.Fail()
	}
}

func TestL(t *testing.T) {
	u := big.NewInt(21)
	n := big.NewInt(3)
	exp := big.NewInt(6)
	if !reflect.DeepEqual(exp, L(u, n)) {
		t.Error("L function is not good")
	}
}

func TestComputeMu(t *testing.T) {
	p := big.NewInt(13)
	q := big.NewInt(11)

	lambda := computeLamda(p, q)
	g := big.NewInt(5000)
	n := new(big.Int).Mul(p, q)

	exp := big.NewInt(3)
	if !reflect.DeepEqual(computeMu(g, lambda, n), exp) {
		t.Error("mu is not well computed")
	}
}

func TestComputeLambda(t *testing.T) {
	a := big.NewInt(5)
	b := big.NewInt(7)
	expected := big.NewInt(12)

	if !reflect.DeepEqual(expected, computeLamda(a, b)) {
		t.Error("lambda is not correctly computed")
	}
}

func TestEncryptDecryptSmall(t *testing.T) {
	p := big.NewInt(13)
	q := big.NewInt(11)
	for i := 1; i < 10; i++ {
		privateKey := CreatePrivateKey(p, q)

		inicialValue := big.NewInt(100)
		cypher, err := privateKey.Encrypt(inicialValue, rand.Reader)
		if err != nil {
			t.Error(err)
		}
		returnedValue := privateKey.Decrypt(cypher)
		if !reflect.DeepEqual(inicialValue, returnedValue) {
			t.Error("wrond decryption ", returnedValue, " is not ", inicialValue)
		}
	}

}

func TestAddCypher(t *testing.T) {
	privateKey := CreatePrivateKey(big.NewInt(13), big.NewInt(11))
	cypher1, _ := privateKey.Encrypt(big.NewInt(12), rand.Reader)
	cypher2, _ := privateKey.Encrypt(big.NewInt(13), rand.Reader)
	cypher3 := privateKey.Add(cypher1, cypher2)
	m := privateKey.Decrypt(cypher3)
	if !reflect.DeepEqual(m, big.NewInt(25)) {
		t.Error(m)
	}
}
<|endoftext|>


<commit_before>package reverseproxy

import (
	"crypto/tls"
	"net"
	"net/http"
	"net/url"
	"strconv"

	"github.com/koding/kite"
	"github.com/koding/kite/config"
	"github.com/koding/websocketproxy"
)

const (
	Version           = "0.0.1"
	Name              = "reverseproxy"
	DefaultPort       = 3999
	DefaultPublicHost = "localhost:3999"
)

type Proxy struct {
	Kite *kite.Kite

	listener  net.Listener
	TLSConfig *tls.Config

	// Holds registered kites. Keys are kite IDs.
	kites map[string]*url.URL

	// muxer for proxy
	mux *http.ServeMux

	// If given it must match the domain in certificate.
	PublicHost string

	RegisterToKontrol bool

	// Proxy URL that get registered to Kontrol
	Url *url.URL
}

func New(conf *config.Config) *Proxy {
	k := kite.New(Name, Version)
	k.Config = conf

	// Listen on 3999 by default
	if k.Config.Port == 0 {
		k.Config.Port = DefaultPort
	}

	p := &Proxy{
		Kite:              k,
		kites:             make(map[string]*url.URL),
		mux:               http.NewServeMux(),
		RegisterToKontrol: true,
		PublicHost:        DefaultPublicHost,
	}
	p.Kite.HandleFunc("register", p.handleRegister)

	proxy := &websocketproxy.WebsocketProxy{
		Backend: p.backend,
	}

	p.mux.Handle("/kite", k)
	p.mux.Handle("/", proxy)

	return p
}

func (p *Proxy) backend(r *http.Request) *url.URL {
	return nil
}

func (p *Proxy) registerURL(scheme string) *url.URL {
	registerURL := p.Url
	if p.Url == nil {
		registerURL = &url.URL{
			Scheme: scheme,
			Host:   p.PublicHost,
			Path:   "/kite",
		}
	}

	return registerURL
}

// ListenAndServe listens on the TCP network address addr and then calls Serve
// with handler to handle requests on incoming connections. Handler is
// typically nil, in which case the DefaultServeMux is used.
func (p *Proxy) ListenAndServe() error {
	var err error
	p.listener, err = net.Listen("tcp",
		net.JoinHostPort(p.Kite.Config.IP, strconv.Itoa(p.Kite.Config.Port)))

	if err != nil {
		return err
	}

	if p.RegisterToKontrol {
		go p.Kite.RegisterForever(p.registerURL("ws"))
	}

	server := http.Server{
		Handler: p.mux,
	}

	defer p.Kite.Close()
	return server.Serve(p.listener)
}

func (p *Proxy) ListenAndServeTLS(certFile, keyFile string) error {
	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		p.Kite.Log.Fatal(err.Error())
	}

	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
	}

	p.listener, err = net.Listen("tcp",
		net.JoinHostPort(p.Kite.Config.IP, strconv.Itoa(p.Kite.Config.Port)))
	if err != nil {
		p.Kite.Log.Fatal(err.Error())
	}

	p.listener = tls.NewListener(p.listener, tlsConfig)

	if p.RegisterToKontrol {
		go p.Kite.RegisterForever(p.registerURL("wss"))
	}

	server := &http.Server{
		Handler:   p.mux,
		TLSConfig: tlsConfig,
	}

	defer p.Kite.Close()
	return server.Serve(p.listener)
}

func (p *Proxy) handleRegister(r *kite.Request) (interface{}, error) {
	p.kites[r.Client.ID] = r.Client.WSConfig.Location

	proxyURL := url.URL{
		Scheme:   p.Url.Scheme,
		Host:     p.Url.Host,
		Path:     "proxy",
		RawQuery: "kiteID=" + r.Client.ID,
	}

	return proxyURL.String(), nil
}
<commit_msg>reverseproxy: more fixes<commit_after>package reverseproxy

import (
	"crypto/tls"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"sync"

	"github.com/koding/kite"
	"github.com/koding/kite/config"
	"github.com/koding/websocketproxy"
)

const (
	Version           = "0.0.1"
	Name              = "reverseproxy"
	DefaultPort       = 3999
	DefaultPublicHost = "localhost:3999"
)

type Proxy struct {
	Kite *kite.Kite

	listener  net.Listener
	TLSConfig *tls.Config

	// Holds registered kites. Keys are kite IDs.
	kites   map[string]*url.URL
	kitesMu sync.Mutex

	// muxer for proxy
	mux *http.ServeMux

	// If given it must match the domain in certificate.
	PublicHost string

	RegisterToKontrol bool

	// Proxy URL that get registered to Kontrol
	Url *url.URL
}

func New(conf *config.Config) *Proxy {
	k := kite.New(Name, Version)
	k.Config = conf

	// Listen on 3999 by default
	if k.Config.Port == 0 {
		k.Config.Port = DefaultPort
	}

	p := &Proxy{
		Kite:              k,
		kites:             make(map[string]*url.URL),
		mux:               http.NewServeMux(),
		RegisterToKontrol: true,
		PublicHost:        DefaultPublicHost,
	}

	// third part kites are going to use this to register themself to
	// proxy-kite and get a proxy url, which they use for register to kontrol.
	p.Kite.HandleFunc("register", p.handleRegister)

	// create our websocketproxy http.handler
	proxy := &websocketproxy.WebsocketProxy{
		Backend: p.backend,
	}

	p.mux.Handle("/kite", k)
	p.mux.Handle("/proxy", proxy)

	return p
}

func (p *Proxy) handleRegister(r *kite.Request) (interface{}, error) {
	p.kites[r.Client.ID] = r.Client.WSConfig.Location

	proxyURL := url.URL{
		Scheme:   p.Url.Scheme,
		Host:     p.Url.Host,
		Path:     "proxy",
		RawQuery: "kiteId=" + r.Client.ID,
	}

	return proxyURL.String(), nil
}

func (p *Proxy) backend(req *http.Request) *url.URL {
	kiteId := req.URL.Query().Get("kiteId")

	p.kitesMu.Lock()
	defer p.kitesMu.Unlock()

	backendURL, ok := p.kites[kiteId]
	if !ok {
		p.Kite.Log.Error("kite for id '%s' is not found: %s", kiteId, req.URL.String())
		return nil
	}

	return backendURL
}

func (p *Proxy) registerURL(scheme string) *url.URL {
	registerURL := p.Url
	if p.Url == nil {
		registerURL = &url.URL{
			Scheme: scheme,
			Host:   p.PublicHost,
			Path:   "/kite",
		}
	}

	return registerURL
}

// ListenAndServe listens on the TCP network address addr and then calls Serve
// with handler to handle requests on incoming connections. Handler is
// typically nil, in which case the DefaultServeMux is used.
func (p *Proxy) ListenAndServe() error {
	var err error
	p.listener, err = net.Listen("tcp",
		net.JoinHostPort(p.Kite.Config.IP, strconv.Itoa(p.Kite.Config.Port)))

	if err != nil {
		return err
	}

	if p.RegisterToKontrol {
		go p.Kite.RegisterForever(p.registerURL("ws"))
	}

	server := http.Server{
		Handler: p.mux,
	}

	defer p.Kite.Close()
	return server.Serve(p.listener)
}

func (p *Proxy) ListenAndServeTLS(certFile, keyFile string) error {
	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		p.Kite.Log.Fatal(err.Error())
	}

	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
	}

	p.listener, err = net.Listen("tcp",
		net.JoinHostPort(p.Kite.Config.IP, strconv.Itoa(p.Kite.Config.Port)))
	if err != nil {
		p.Kite.Log.Fatal(err.Error())
	}

	p.listener = tls.NewListener(p.listener, tlsConfig)

	if p.RegisterToKontrol {
		go p.Kite.RegisterForever(p.registerURL("wss"))
	}

	server := &http.Server{
		Handler:   p.mux,
		TLSConfig: tlsConfig,
	}

	defer p.Kite.Close()
	return server.Serve(p.listener)
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
	"github.com/qor/qor/admin"
	"github.com/qor/qor/l10n"
	"github.com/qor/qor/media_library"
	"github.com/qor/qor/publish"
)

type CreditCard struct {
	ID     int
	Number string
	Issuer string
}

type Address struct {
	ID       int
	UserId   int64
	Address1 string
	Address2 string
}

type Role struct {
	ID   int
	Name string
}

type Language struct {
	ID   int
	Name string
}

type User struct {
	ID           int
	Name         string
	Gender       string
	Description  string
	File         media_library.FileSystem
	RoleID       int
	Languages    []Language `gorm:"many2many:user_languages;"`
	CreditCard   CreditCard
	CreditCardID int
	Addresses    []Address
	DeletedAt    time.Time
	publish.Status
}

func (User) ViewableLocales() []string {
	return []string{l10n.Global, "zh-CN", "JP", "EN", "DE"}
}

func (user User) EditableLocales() []string {
	if user.Name == "global_admin" {
		return []string{l10n.Global, "zh-CN", "EN"}
	} else {
		return []string{"zh-CN", "EN"}
	}
}

func (u User) DisplayName() string {
	return u.Name
}

type Product struct {
	ID          int
	Name        *string
	Description *string
	CreatedAt   time.Time
	UpdatedAt   time.Time
	DeletedAt   time.Time
	l10n.Locale
	publish.Status
}

var DB gorm.DB
var Publish *publish.Publish

func init() {
	var err error
	// CREATE USER 'qor' IDENTIFIED BY 'qor';
	// CREATE DATABASE qor_example;
	// GRANT ALL PRIVILEGES ON qor_example.* TO 'qor';
	DB, err = gorm.Open("mysql", "qor:qor@/qor_example?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}

	DB.AutoMigrate(&User{}, &CreditCard{}, &Address{}, &Role{}, &Language{}, &Product{}, &admin.AssetManager{})

	Publish = publish.New(&DB)
	Publish.Support(&Product{}).AutoMigrate()

	l10n.RegisterCallbacks(&DB)

	var AdminRole Role
	DB.FirstOrCreate(&AdminRole, Role{Name: "admin"})
	DB.FirstOrCreate(&Role{}, Role{Name: "dev"})
	DB.FirstOrCreate(&Role{}, Role{Name: "customer_support"})

	DB.FirstOrCreate(&User{}, User{Name: "admin", RoleID: AdminRole.ID})
	DB.FirstOrCreate(&User{}, User{Name: "global_admin", RoleID: AdminRole.ID})

	DB.FirstOrCreate(&Language{}, Language{Name: "CN"})
	DB.FirstOrCreate(&Language{}, Language{Name: "JP"})
	DB.FirstOrCreate(&Language{}, Language{Name: "EN"})
	DB.FirstOrCreate(&Language{}, Language{Name: "DE"})

	DB.LogMode(true)
}
<commit_msg>Disable DB log<commit_after>package main

import (
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
	"github.com/qor/qor/admin"
	"github.com/qor/qor/l10n"
	"github.com/qor/qor/media_library"
	"github.com/qor/qor/publish"
)

type CreditCard struct {
	ID     int
	Number string
	Issuer string
}

type Address struct {
	ID       int
	UserId   int64
	Address1 string
	Address2 string
}

type Role struct {
	ID   int
	Name string
}

type Language struct {
	ID   int
	Name string
}

type User struct {
	ID           int
	Name         string
	Gender       string
	Description  string
	File         media_library.FileSystem
	RoleID       int
	Languages    []Language `gorm:"many2many:user_languages;"`
	CreditCard   CreditCard
	CreditCardID int
	Addresses    []Address
	DeletedAt    time.Time
	publish.Status
}

func (User) ViewableLocales() []string {
	return []string{l10n.Global, "zh-CN", "JP", "EN", "DE"}
}

func (user User) EditableLocales() []string {
	if user.Name == "global_admin" {
		return []string{l10n.Global, "zh-CN", "EN"}
	} else {
		return []string{"zh-CN", "EN"}
	}
}

func (u User) DisplayName() string {
	return u.Name
}

type Product struct {
	ID          int
	Name        *string
	Description *string
	CreatedAt   time.Time
	UpdatedAt   time.Time
	DeletedAt   time.Time
	l10n.Locale
	publish.Status
}

var DB gorm.DB
var Publish *publish.Publish

func init() {
	var err error
	// CREATE USER 'qor' IDENTIFIED BY 'qor';
	// CREATE DATABASE qor_example;
	// GRANT ALL PRIVILEGES ON qor_example.* TO 'qor';
	DB, err = gorm.Open("mysql", "qor:qor@/qor_example?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}

	DB.AutoMigrate(&User{}, &CreditCard{}, &Address{}, &Role{}, &Language{}, &Product{}, &admin.AssetManager{})

	Publish = publish.New(&DB)
	Publish.Support(&Product{}).AutoMigrate()

	l10n.RegisterCallbacks(&DB)

	var AdminRole Role
	DB.FirstOrCreate(&AdminRole, Role{Name: "admin"})
	DB.FirstOrCreate(&Role{}, Role{Name: "dev"})
	DB.FirstOrCreate(&Role{}, Role{Name: "customer_support"})

	DB.FirstOrCreate(&User{}, User{Name: "admin", RoleID: AdminRole.ID})
	DB.FirstOrCreate(&User{}, User{Name: "global_admin", RoleID: AdminRole.ID})

	DB.FirstOrCreate(&Language{}, Language{Name: "CN"})
	DB.FirstOrCreate(&Language{}, Language{Name: "JP"})
	DB.FirstOrCreate(&Language{}, Language{Name: "EN"})
	DB.FirstOrCreate(&Language{}, Language{Name: "DE"})

	DB.LogMode(false)
}
<|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.

// UTF-8 support.

package utf8

const (
	RuneError = 0xFFFD;
	RuneSelf = 0x80;
	RuneMax = 0x10FFFF;
	UTFMax = 4;
)

const (
	_T1 = 0x00;	// 0000 0000
	_Tx = 0x80;	// 1000 0000
	_T2 = 0xC0;	// 1100 0000
	_T3 = 0xE0;	// 1110 0000
	_T4 = 0xF0;	// 1111 0000
	_T5 = 0xF8;	// 1111 1000

	_Maskx = 0x3F;	// 0011 1111
	_Mask2 = 0x1F;	// 0001 1111
	_Mask3 = 0x0F;	// 0000 1111
	_Mask4 = 0x07;	// 0000 0111

	_Rune1Max = 1<<7 - 1;
	_Rune2Max = 1<<11 - 1;
	_Rune3Max = 1<<16 - 1;
	_Rune4Max = 1<<21 - 1;
)

func decodeRuneInternal(p []byte) (rune, size int, short bool) {
	n := len(p);
	if n < 1 {
		return RuneError, 0, true;
	}
	c0 := p[0];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := p[1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := p[2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := p[3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false
	}

	// error
	return RuneError, 1, false
}

func decodeRuneInStringInternal(s string, i int, n int) (rune, size int, short bool) {
	if n < 1 {
		return RuneError, 0, true;
	}
	c0 := s[i];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := s[i+1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := s[i+2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := s[i+3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false
	}

	// error
	return RuneError, 1, false
}

func FullRune(p []byte) bool {
	rune, size, short := decodeRuneInternal(p);
	return !short
}

func FullRuneInString(s string, i int) bool {
	rune, size, short := decodeRuneInStringInternal(s, i, len(s) - i);
	return !short
}

func DecodeRune(p []byte) (rune, size int) {
	var short bool;
	rune, size, short = decodeRuneInternal(p);
	return;
}

func DecodeRuneInString(s string, i int) (rune, size int) {
	var short bool;
	rune, size, short = decodeRuneInStringInternal(s, i, len(s) - i);
	return;
}

func RuneLen(rune int) int {
	switch {
	case rune <= _Rune1Max:
		return 1;
	case rune <= _Rune2Max:
		return 2;
	case rune <= _Rune3Max:
		return 3;
	case rune <= _Rune4Max:
		return 4;
	}
	return -1;
}

func EncodeRune(rune int, p []byte) int {
	if rune <= _Rune1Max {
		p[0] = byte(rune);
		return 1;
	}

	if rune <= _Rune2Max {
		p[0] = _T2 | byte(rune>>6);
		p[1] = _Tx | byte(rune)&_Maskx;
		return 2;
	}

	if rune > RuneMax {
		rune = RuneError
	}

	if rune <= _Rune3Max {
		p[0] = _T3 | byte(rune>>12);
		p[1] = _Tx | byte(rune>>6)&_Maskx;
		p[2] = _Tx | byte(rune)&_Maskx;
		return 3;
	}

	p[0] = _T4 | byte(rune>>18);
	p[1] = _Tx | byte(rune>>12)&_Maskx;
	p[2] = _Tx | byte(rune>>6)&_Maskx;
	p[3] = _Tx | byte(rune)&_Maskx;
	return 4;
}

func RuneCount(p []byte) int {
	i := 0;
	var n int;
	for n = 0; i < len(p); n++ {
		if p[i] < RuneSelf {
			i++;
		} else {
			rune, size := DecodeRune(p[i:len(p)]);
			i += size;
		}
	}
	return n;
}

func RuneCountInString(s string, i int, l int) int {
	ei := i + l;
	n := 0;
	for n = 0; i < ei; n++ {
		if s[i] < RuneSelf {
			i++;
		} else {
			rune, size, short := decodeRuneInStringInternal(s, i, ei - i);
			i += size;
		}
	}
	return n;
}

<commit_msg>document utf8<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.

// Functions and constants to support text encoded in UTF-8.
// This package calls a Unicode character a rune for brevity.
package utf8

// Numbers fundamental to the encoding.
const (
	RuneError = 0xFFFD;	// the "error" Rune or "replacement character".
	RuneSelf = 0x80;	// characters below Runeself are represented as themselves in a single byte.
	RuneMax = 0x10FFFF;	// maximum Unicode code point.
	UTFMax = 4;	// maximum number of bytes of a UTF-8 encoded Unicode character.
)

const (
	_T1 = 0x00;	// 0000 0000
	_Tx = 0x80;	// 1000 0000
	_T2 = 0xC0;	// 1100 0000
	_T3 = 0xE0;	// 1110 0000
	_T4 = 0xF0;	// 1111 0000
	_T5 = 0xF8;	// 1111 1000

	_Maskx = 0x3F;	// 0011 1111
	_Mask2 = 0x1F;	// 0001 1111
	_Mask3 = 0x0F;	// 0000 1111
	_Mask4 = 0x07;	// 0000 0111

	_Rune1Max = 1<<7 - 1;
	_Rune2Max = 1<<11 - 1;
	_Rune3Max = 1<<16 - 1;
	_Rune4Max = 1<<21 - 1;
)

func decodeRuneInternal(p []byte) (rune, size int, short bool) {
	n := len(p);
	if n < 1 {
		return RuneError, 0, true;
	}
	c0 := p[0];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := p[1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := p[2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := p[3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false
	}

	// error
	return RuneError, 1, false
}

func decodeRuneInStringInternal(s string, i int, n int) (rune, size int, short bool) {
	if n < 1 {
		return RuneError, 0, true;
	}
	c0 := s[i];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := s[i+1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := s[i+2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := s[i+3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false
	}

	// error
	return RuneError, 1, false
}

// FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
func FullRune(p []byte) bool {
	rune, size, short := decodeRuneInternal(p);
	return !short
}

// FullRuneInString is like FullRune but its input is a string.
func FullRuneInString(s string, i int) bool {
	rune, size, short := decodeRuneInStringInternal(s, i, len(s) - i);
	return !short
}

// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
func DecodeRune(p []byte) (rune, size int) {
	var short bool;
	rune, size, short = decodeRuneInternal(p);
	return;
}

// DecodeRuneInString is like DecodeRune but its input is a string.
func DecodeRuneInString(s string, i int) (rune, size int) {
	var short bool;
	rune, size, short = decodeRuneInStringInternal(s, i, len(s) - i);
	return;
}

// RuneLen returns the number of bytes required to encode the rune.
func RuneLen(rune int) int {
	switch {
	case rune <= _Rune1Max:
		return 1;
	case rune <= _Rune2Max:
		return 2;
	case rune <= _Rune3Max:
		return 3;
	case rune <= _Rune4Max:
		return 4;
	}
	return -1;
}

// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
// It returns the number of bytes written.
func EncodeRune(rune int, p []byte) int {
	if rune <= _Rune1Max {
		p[0] = byte(rune);
		return 1;
	}

	if rune <= _Rune2Max {
		p[0] = _T2 | byte(rune>>6);
		p[1] = _Tx | byte(rune)&_Maskx;
		return 2;
	}

	if rune > RuneMax {
		rune = RuneError
	}

	if rune <= _Rune3Max {
		p[0] = _T3 | byte(rune>>12);
		p[1] = _Tx | byte(rune>>6)&_Maskx;
		p[2] = _Tx | byte(rune)&_Maskx;
		return 3;
	}

	p[0] = _T4 | byte(rune>>18);
	p[1] = _Tx | byte(rune>>12)&_Maskx;
	p[2] = _Tx | byte(rune>>6)&_Maskx;
	p[3] = _Tx | byte(rune)&_Maskx;
	return 4;
}

// RuneCount returns the number of runes in p.  Erroneous and short
// encodings are treated as single runes of width 1 byte.
func RuneCount(p []byte) int {
	i := 0;
	var n int;
	for n = 0; i < len(p); n++ {
		if p[i] < RuneSelf {
			i++;
		} else {
			rune, size := DecodeRune(p[i:len(p)]);
			i += size;
		}
	}
	return n;
}

// RuneCountInString is like RuneCount but its input is a string.
func RuneCountInString(s string, i int, l int) int {
	ei := i + l;
	n := 0;
	for n = 0; i < ei; n++ {
		if s[i] < RuneSelf {
			i++;
		} else {
			rune, size, short := decodeRuneInStringInternal(s, i, ei - i);
			i += size;
		}
	}
	return n;
}

<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"unicode"

	. "goprotobuf.googlecode.com/hg/compiler/descriptor"
	"goprotobuf.googlecode.com/hg/proto"
)

func ParseFiles(filenames []string) (*FileDescriptorSet, os.Error) {
	fds := &FileDescriptorSet{
		File: make([]*FileDescriptorProto, len(filenames)),
	}

	for i, filename := range filenames {
		fds.File[i] = &FileDescriptorProto{
			Name: proto.String(filename),
		}
		buf, err := ioutil.ReadFile(filename)
		if err != nil {
			return nil, err
		}

		p := newParser(string(buf))
		if pe := p.readFile(fds.File[i]); pe != nil {
			return nil, pe
		}
		if p.s != "" {
			return nil, p.error("input was not all consumed")
		}
	}

	return fds, nil
}

type parseError struct {
	message string
	line    int // 1-based line number
	offset  int // 0-based byte offset from start of input
}

func (pe *parseError) String() string {
	if pe == nil {
		return "<nil>"
	}
	if pe.line == 1 {
		return fmt.Sprintf("line 1.%d: %v", pe.offset, pe.message)
	}
	return fmt.Sprintf("line %d: %v", pe.line, pe.message)
}

type token struct {
	value        string
	err          *parseError
	line, offset int
}

type parser struct {
	s            string // remaining input
	done         bool   // whether the parsing is finished
	backed       bool   // whether back() was called
	offset, line int
	cur          token
}

func newParser(s string) *parser {
	return &parser{
		s:    s,
		line: 1,
		cur: token{
			line: 1,
		},
	}
}

func (p *parser) readFile(fd *FileDescriptorProto) *parseError {
	// Parse the top-level things.
	for !p.done {
		tok := p.next()
		if tok.err != nil {
			return tok.err
		}
		switch tok.value {
		case "package":
			tok := p.next()
			if tok.err != nil {
				return tok.err
			}
			// TODO: check for a good package name
			fd.Package = proto.String(tok.value)

			if err := p.readToken(";"); err != nil {
				return err
			}
		case "message":
			p.back()
			msg := new(DescriptorProto)
			fd.MessageType = append(fd.MessageType, msg)
			if err := p.readMessage(msg); err != nil {
				return err
			}
		// TODO: more top-level things
		case "":
			// EOF
			break
		default:
			return p.error("unknown top-level thing %q", tok.value)
		}
	}

	// TODO: more

	return nil
}

func (p *parser) readMessage(d *DescriptorProto) *parseError {
	if err := p.readToken("message"); err != nil {
		return err
	}

	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	// TODO: check that the name is acceptable.
	d.Name = proto.String(tok.value)

	if err := p.readToken("{"); err != nil {
		return err
	}

	// Parse message fields and other things inside messages.
	for !p.done {
		tok := p.next()
		if tok.err != nil {
			return tok.err
		}
		switch tok.value {
		case "required", "optional", "repeated":
			// field
			p.back()
			f := new(FieldDescriptorProto)
			d.Field = append(d.Field, f)
			if err := p.readField(f); err != nil {
				return err
			}
		case "message":
			// inner message
			p.back()
			msg := new(DescriptorProto)
			d.NestedType = append(d.NestedType, msg)
			if err := p.readMessage(msg); err != nil {
				return err
			}
		// TODO: more message contents
		case "}":
			// end of message
			return nil
		}
	}

	return p.error("unexpected end while parsing message")
}

var fieldLabelMap = map[string]*FieldDescriptorProto_Label{
	"required": NewFieldDescriptorProto_Label(FieldDescriptorProto_LABEL_REQUIRED),
	"optional": NewFieldDescriptorProto_Label(FieldDescriptorProto_LABEL_OPTIONAL),
	"repeated": NewFieldDescriptorProto_Label(FieldDescriptorProto_LABEL_REPEATED),
}

var fieldTypeMap = map[string]*FieldDescriptorProto_Type{
	// Only basic types; enum, message and group are handled differently.
	"double":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_DOUBLE),
	"float":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_FLOAT),
	"int64":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_INT64),
	"uint64":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_UINT64),
	"int32":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_INT32),
	"fixed64":  NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_FIXED64),
	"fixed32":  NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_FIXED32),
	"bool":     NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_BOOL),
	"string":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_STRING),
	"bytes":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_BYTES),
	"uint32":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_UINT32),
	"sfixed32": NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SFIXED32),
	"sfixed64": NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SFIXED64),
	"sint32":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SINT32),
	"sint64":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SINT64),
}

func (p *parser) readField(f *FieldDescriptorProto) *parseError {
	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	if lab, ok := fieldLabelMap[tok.value]; ok {
		f.Label = lab
	} else {
		return p.error("expected required/optional/repeated, found %q", tok.value)
	}

	tok = p.next()
	if tok.err != nil {
		return tok.err
	}
	if typ, ok := fieldTypeMap[tok.value]; ok {
		f.Type = typ
	} else {
		// TODO: type names need checking; this just guesses it's a message, but it could be an enum.
		f.TypeName = proto.String(tok.value)
	}

	tok = p.next()
	if tok.err != nil {
		return tok.err
	}
	// TODO: check field name correctness (character set, etc.)
	f.Name = proto.String(tok.value)

	if err := p.readToken("="); err != nil {
		return err
	}

	tok = p.next()
	if tok.err != nil {
		return tok.err
	}
	num, err := atoi32(tok.value)
	if err != nil {
		return p.error("bad field number %q: %v", tok.value, err)
	}
	f.Number = proto.Int32(num)

	// TODO: default value, options

	if err := p.readToken(";"); err != nil {
		return err
	}

	return nil
}

func (p *parser) readToken(expected string) *parseError {
	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	if tok.value != expected {
		return p.error("expected %q, found %q", expected, tok.value)
	}
	return nil
}

// Back off the parser by one token; may only be done between calls to p.next().
func (p *parser) back() {
	p.backed = true
}

// Advances the parser and returns the new current token.
func (p *parser) next() *token {
	if p.backed || p.done {
		p.backed = false
	} else {
		p.advance()
		if p.done {
			p.cur.value = ""
		}
	}
	log.Printf("parser·next(): returning %q [err: %v]", p.cur.value, p.cur.err)
	return &p.cur
}

func (p *parser) advance() {
	// Skip whitespace
	p.skipWhitespaceAndComments()
	if p.done {
		return
	}

	// Start of non-whitespace
	p.cur.err = nil
	p.cur.offset, p.cur.line = p.offset, p.line
	switch p.s[0] {
	// TODO: more cases, like punctuation.
	case ';', '{', '}', '=':
		// Single symbol
		p.cur.value, p.s = p.s[:1], p.s[1:]
	default:
		i := 0
		for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
			i++
		}
		if i == 0 {
			p.error("unexpected byte 0x%02x (%q)", p.s[0], string(p.s[:1]))
			return
		}
		p.cur.value, p.s = p.s[:i], p.s[i:]
	}
	p.offset += len(p.cur.value)
}

func (p *parser) skipWhitespaceAndComments() {
	i := 0
	for i < len(p.s) {
		if isWhitespace(p.s[i]) {
			if p.s[i] == '\n' {
				p.line++
			}
			i++
			continue
		}
		if i+1 < len(p.s) && p.s[i] == '/' && p.s[i+1] == '/' {
			// comment; skip to end of line or input
			for i < len(p.s) && p.s[i] != '\n' {
				i++
			}
			if i < len(p.s) {
				// end of line; keep going
				p.line++
				i++
				continue
			}
			// end of input; fall out of loop
		}
		break
	}
	p.offset += i
	p.s = p.s[i:]
	if len(p.s) == 0 {
		p.done = true
	}
}

func (p *parser) error(format string, a ...interface{}) *parseError {
	pe := &parseError{
		message: fmt.Sprintf(format, a...),
		line:    p.cur.line,
		offset:  p.cur.offset,
	}
	p.cur.err = pe
	p.done = true
	return pe
}

func isWhitespace(c byte) bool {
	// TODO: do more accurately
	return unicode.IsSpace(int(c))
}

// Numbers and identifiers are matched by [-+._A-Za-z0-9]
func isIdentOrNumberChar(c byte) bool {
	switch {
	case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
		return true
	case '0' <= c && c <= '9':
		return true
	}
	switch c {
	case '-', '+', '.', '_':
		return true
	}
	return false
}

func atoi32(s string) (int32, os.Error) {
	x, err := strconv.Atoi64(s)
	if err != nil {
		return 0, err
	}
	if x < (-1 << 31) || x > (1<<31 - 1) {
		return 0, os.NewError("out of int32 range")
	}
	return int32(x), nil
}
<commit_msg>Quieten parser.<commit_after>package parser

import (
	"fmt"
	"io/ioutil"
	//"log"
	"os"
	"strconv"
	"unicode"

	. "goprotobuf.googlecode.com/hg/compiler/descriptor"
	"goprotobuf.googlecode.com/hg/proto"
)

func ParseFiles(filenames []string) (*FileDescriptorSet, os.Error) {
	fds := &FileDescriptorSet{
		File: make([]*FileDescriptorProto, len(filenames)),
	}

	for i, filename := range filenames {
		fds.File[i] = &FileDescriptorProto{
			Name: proto.String(filename),
		}
		buf, err := ioutil.ReadFile(filename)
		if err != nil {
			return nil, err
		}

		p := newParser(string(buf))
		if pe := p.readFile(fds.File[i]); pe != nil {
			return nil, pe
		}
		if p.s != "" {
			return nil, p.error("input was not all consumed")
		}
	}

	return fds, nil
}

type parseError struct {
	message string
	line    int // 1-based line number
	offset  int // 0-based byte offset from start of input
}

func (pe *parseError) String() string {
	if pe == nil {
		return "<nil>"
	}
	if pe.line == 1 {
		return fmt.Sprintf("line 1.%d: %v", pe.offset, pe.message)
	}
	return fmt.Sprintf("line %d: %v", pe.line, pe.message)
}

type token struct {
	value        string
	err          *parseError
	line, offset int
}

type parser struct {
	s            string // remaining input
	done         bool   // whether the parsing is finished
	backed       bool   // whether back() was called
	offset, line int
	cur          token
}

func newParser(s string) *parser {
	return &parser{
		s:    s,
		line: 1,
		cur: token{
			line: 1,
		},
	}
}

func (p *parser) readFile(fd *FileDescriptorProto) *parseError {
	// Parse the top-level things.
	for !p.done {
		tok := p.next()
		if tok.err != nil {
			return tok.err
		}
		switch tok.value {
		case "package":
			tok := p.next()
			if tok.err != nil {
				return tok.err
			}
			// TODO: check for a good package name
			fd.Package = proto.String(tok.value)

			if err := p.readToken(";"); err != nil {
				return err
			}
		case "message":
			p.back()
			msg := new(DescriptorProto)
			fd.MessageType = append(fd.MessageType, msg)
			if err := p.readMessage(msg); err != nil {
				return err
			}
		// TODO: more top-level things
		case "":
			// EOF
			break
		default:
			return p.error("unknown top-level thing %q", tok.value)
		}
	}

	// TODO: more

	return nil
}

func (p *parser) readMessage(d *DescriptorProto) *parseError {
	if err := p.readToken("message"); err != nil {
		return err
	}

	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	// TODO: check that the name is acceptable.
	d.Name = proto.String(tok.value)

	if err := p.readToken("{"); err != nil {
		return err
	}

	// Parse message fields and other things inside messages.
	for !p.done {
		tok := p.next()
		if tok.err != nil {
			return tok.err
		}
		switch tok.value {
		case "required", "optional", "repeated":
			// field
			p.back()
			f := new(FieldDescriptorProto)
			d.Field = append(d.Field, f)
			if err := p.readField(f); err != nil {
				return err
			}
		case "message":
			// inner message
			p.back()
			msg := new(DescriptorProto)
			d.NestedType = append(d.NestedType, msg)
			if err := p.readMessage(msg); err != nil {
				return err
			}
		// TODO: more message contents
		case "}":
			// end of message
			return nil
		}
	}

	return p.error("unexpected end while parsing message")
}

var fieldLabelMap = map[string]*FieldDescriptorProto_Label{
	"required": NewFieldDescriptorProto_Label(FieldDescriptorProto_LABEL_REQUIRED),
	"optional": NewFieldDescriptorProto_Label(FieldDescriptorProto_LABEL_OPTIONAL),
	"repeated": NewFieldDescriptorProto_Label(FieldDescriptorProto_LABEL_REPEATED),
}

var fieldTypeMap = map[string]*FieldDescriptorProto_Type{
	// Only basic types; enum, message and group are handled differently.
	"double":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_DOUBLE),
	"float":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_FLOAT),
	"int64":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_INT64),
	"uint64":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_UINT64),
	"int32":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_INT32),
	"fixed64":  NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_FIXED64),
	"fixed32":  NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_FIXED32),
	"bool":     NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_BOOL),
	"string":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_STRING),
	"bytes":    NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_BYTES),
	"uint32":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_UINT32),
	"sfixed32": NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SFIXED32),
	"sfixed64": NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SFIXED64),
	"sint32":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SINT32),
	"sint64":   NewFieldDescriptorProto_Type(FieldDescriptorProto_TYPE_SINT64),
}

func (p *parser) readField(f *FieldDescriptorProto) *parseError {
	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	if lab, ok := fieldLabelMap[tok.value]; ok {
		f.Label = lab
	} else {
		return p.error("expected required/optional/repeated, found %q", tok.value)
	}

	tok = p.next()
	if tok.err != nil {
		return tok.err
	}
	if typ, ok := fieldTypeMap[tok.value]; ok {
		f.Type = typ
	} else {
		// TODO: type names need checking; this just guesses it's a message, but it could be an enum.
		f.TypeName = proto.String(tok.value)
	}

	tok = p.next()
	if tok.err != nil {
		return tok.err
	}
	// TODO: check field name correctness (character set, etc.)
	f.Name = proto.String(tok.value)

	if err := p.readToken("="); err != nil {
		return err
	}

	tok = p.next()
	if tok.err != nil {
		return tok.err
	}
	num, err := atoi32(tok.value)
	if err != nil {
		return p.error("bad field number %q: %v", tok.value, err)
	}
	f.Number = proto.Int32(num)

	// TODO: default value, options

	if err := p.readToken(";"); err != nil {
		return err
	}

	return nil
}

func (p *parser) readToken(expected string) *parseError {
	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	if tok.value != expected {
		return p.error("expected %q, found %q", expected, tok.value)
	}
	return nil
}

// Back off the parser by one token; may only be done between calls to p.next().
func (p *parser) back() {
	p.backed = true
}

// Advances the parser and returns the new current token.
func (p *parser) next() *token {
	if p.backed || p.done {
		p.backed = false
	} else {
		p.advance()
		if p.done {
			p.cur.value = ""
		}
	}
	//log.Printf("parser·next(): returning %q [err: %v]", p.cur.value, p.cur.err)
	return &p.cur
}

func (p *parser) advance() {
	// Skip whitespace
	p.skipWhitespaceAndComments()
	if p.done {
		return
	}

	// Start of non-whitespace
	p.cur.err = nil
	p.cur.offset, p.cur.line = p.offset, p.line
	switch p.s[0] {
	// TODO: more cases, like punctuation.
	case ';', '{', '}', '=':
		// Single symbol
		p.cur.value, p.s = p.s[:1], p.s[1:]
	default:
		i := 0
		for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
			i++
		}
		if i == 0 {
			p.error("unexpected byte 0x%02x (%q)", p.s[0], string(p.s[:1]))
			return
		}
		p.cur.value, p.s = p.s[:i], p.s[i:]
	}
	p.offset += len(p.cur.value)
}

func (p *parser) skipWhitespaceAndComments() {
	i := 0
	for i < len(p.s) {
		if isWhitespace(p.s[i]) {
			if p.s[i] == '\n' {
				p.line++
			}
			i++
			continue
		}
		if i+1 < len(p.s) && p.s[i] == '/' && p.s[i+1] == '/' {
			// comment; skip to end of line or input
			for i < len(p.s) && p.s[i] != '\n' {
				i++
			}
			if i < len(p.s) {
				// end of line; keep going
				p.line++
				i++
				continue
			}
			// end of input; fall out of loop
		}
		break
	}
	p.offset += i
	p.s = p.s[i:]
	if len(p.s) == 0 {
		p.done = true
	}
}

func (p *parser) error(format string, a ...interface{}) *parseError {
	pe := &parseError{
		message: fmt.Sprintf(format, a...),
		line:    p.cur.line,
		offset:  p.cur.offset,
	}
	p.cur.err = pe
	p.done = true
	return pe
}

func isWhitespace(c byte) bool {
	// TODO: do more accurately
	return unicode.IsSpace(int(c))
}

// Numbers and identifiers are matched by [-+._A-Za-z0-9]
func isIdentOrNumberChar(c byte) bool {
	switch {
	case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
		return true
	case '0' <= c && c <= '9':
		return true
	}
	switch c {
	case '-', '+', '.', '_':
		return true
	}
	return false
}

func atoi32(s string) (int32, os.Error) {
	x, err := strconv.Atoi64(s)
	if err != nil {
		return 0, err
	}
	if x < (-1 << 31) || x > (1<<31 - 1) {
		return 0, os.NewError("out of int32 range")
	}
	return int32(x), nil
}
<|endoftext|>


<commit_before>package parser

import (
	"errors"
	"fmt"
	"regexp"
	"strings"

	"github.com/gorilla/css/scanner"

	"github.com/aymerick/douceur/css"
)

const (
	IMPORTANT_SUFFIX_REGEXP = `(?i)\s*!important\s*$`
)

var (
	importantRegexp *regexp.Regexp
)

type Parser struct {
	scan *scanner.Scanner // Tokenizer

	// Tokens parsed but not consumed yet
	tokens []*scanner.Token

	// Rule embedding level
	embedLevel int
}

func init() {
	importantRegexp, _ = regexp.Compile(IMPORTANT_SUFFIX_REGEXP)
}

// Instanciate a new parser
func NewParser(txt string) *Parser {
	return &Parser{
		scan: scanner.New(txt),
	}
}

// Parse a whole stylesheet
func Parse(text string) (*css.Stylesheet, error) {
	result, err := NewParser(text).ParseStylesheet()
	if err != nil {
		return nil, err
	} else {
		return result, nil
	}
}

// Parse CSS declarations
func ParseDeclarations(text string) ([]*css.Declaration, error) {
	result, err := NewParser(text).ParseDeclarations()
	if err != nil {
		return nil, err
	} else {
		return result, nil
	}
}

// Parse a stylesheet
func (parser *Parser) ParseStylesheet() (*css.Stylesheet, error) {
	result := css.NewStylesheet()

	// Parse BOM
	if _, err := parser.parseBOM(); err != nil {
		return result, err
	}

	// Parse list of rules
	rules, err := parser.ParseRules()
	if err != nil {
		return result, err
	}

	result.Rules = rules

	return result, nil
}

// Parse a list of rules
func (parser *Parser) ParseRules() ([]*css.Rule, error) {
	result := []*css.Rule{}

	inBlock := false
	if parser.tokenChar("{") {
		// parsing a block of rules
		inBlock = true
		parser.embedLevel += 1

		parser.shiftToken()
	}

	for parser.tokenParsable() {
		if parser.tokenIgnorable() {
			parser.shiftToken()
		} else if parser.tokenChar("}") {
			if !inBlock {
				errMsg := fmt.Sprintf("Unexpected } character: %s", parser.nextToken().String())
				return result, errors.New(errMsg)
			}

			parser.shiftToken()
			parser.embedLevel -= 1

			// finished
			break
		} else {
			rule, err := parser.ParseRule()
			if err != nil {
				return result, err
			}

			rule.EmbedLevel = parser.embedLevel
			result = append(result, rule)
		}
	}

	return result, parser.err()
}

// Parse a rule
func (parser *Parser) ParseRule() (*css.Rule, error) {
	if parser.tokenAtKeyword() {
		return parser.parseAtRule()
	} else {
		return parser.parseQualifiedRule()
	}
}

// Parse a list of declarations
func (parser *Parser) ParseDeclarations() ([]*css.Declaration, error) {
	result := []*css.Declaration{}

	if parser.tokenChar("{") {
		parser.shiftToken()
	}

	for parser.tokenParsable() {
		if parser.tokenIgnorable() {
			parser.shiftToken()
		} else if parser.tokenChar("}") {
			// end of block
			parser.shiftToken()
			break
		} else {
			declaration, err := parser.ParseDeclaration()
			if err != nil {
				return result, err
			}

			result = append(result, declaration)
		}
	}

	return result, parser.err()
}

// Parse a declaration
func (parser *Parser) ParseDeclaration() (*css.Declaration, error) {
	result := css.NewDeclaration()
	curValue := ""

	for parser.tokenParsable() {
		if parser.tokenChar(":") {
			result.Property = strings.TrimSpace(curValue)
			curValue = ""

			parser.shiftToken()
		} else if parser.tokenChar(";") || parser.tokenChar("}") {
			if result.Property == "" {
				errMsg := fmt.Sprintf("Unexpected ; character: %s", parser.nextToken().String())
				return result, errors.New(errMsg)
			}

			if importantRegexp.MatchString(curValue) {
				result.Important = true
				curValue = importantRegexp.ReplaceAllString(curValue, "")
			}

			result.Value = strings.TrimSpace(curValue)

			if parser.tokenChar(";") {
				parser.shiftToken()
			}

			// finished
			break
		} else {
			token := parser.shiftToken()
			curValue += token.Value
		}
	}

	// log.Printf("[parsed] Declaration: %s", result.String())

	return result, parser.err()
}

// Parse an At Rule
func (parser *Parser) parseAtRule() (*css.Rule, error) {
	// parse rule name (eg: "@import")
	token := parser.shiftToken()

	result := css.NewRule(css.AT_RULE)
	result.Name = token.Value

	for parser.tokenParsable() {
		if parser.tokenChar(";") {
			parser.shiftToken()

			// finished
			break
		} else if parser.tokenChar("{") {
			if result.EmbedsRules() {
				// parse rules block
				rules, err := parser.ParseRules()
				if err != nil {
					return result, err
				}

				result.Rules = rules
			} else {
				// parse declarations block
				declarations, err := parser.ParseDeclarations()
				if err != nil {
					return result, err
				}

				result.Declarations = declarations
			}

			// finished
			break
		} else {
			// parse prelude
			prelude, err := parser.parsePrelude()
			if err != nil {
				return result, err
			}

			result.Prelude = prelude
		}
	}

	// log.Printf("[parsed] Rule: %s", result.String())

	return result, parser.err()
}

// Parse a Qualified Rule
func (parser *Parser) parseQualifiedRule() (*css.Rule, error) {
	result := css.NewRule(css.QUALIFIED_RULE)

	for parser.tokenParsable() {
		if parser.tokenChar("{") {
			if result.Prelude == "" {
				errMsg := fmt.Sprintf("Unexpected { character: %s", parser.nextToken().String())
				return result, errors.New(errMsg)
			}

			// parse declarations block
			declarations, err := parser.ParseDeclarations()
			if err != nil {
				return result, err
			}

			result.Declarations = declarations

			// finished
			break
		} else {
			// parse prelude
			prelude, err := parser.parsePrelude()
			if err != nil {
				return result, err
			}

			result.Prelude = prelude
		}
	}

	result.Selectors = strings.Split(result.Prelude, ",")
	for i, sel := range result.Selectors {
		result.Selectors[i] = strings.TrimSpace(sel)
	}

	// log.Printf("[parsed] Rule: %s", result.String())

	return result, parser.err()
}

// Parse Rule prelude
func (parser *Parser) parsePrelude() (string, error) {
	result := ""

	for parser.tokenParsable() && !parser.tokenEndOfPrelude() {
		token := parser.shiftToken()
		result += token.Value
	}

	result = strings.TrimSpace(result)

	// log.Printf("[parsed] prelude: %s", result)

	return result, parser.err()
}

// Parse BOM
func (parser *Parser) parseBOM() (bool, error) {
	if parser.nextToken().Type == scanner.TokenBOM {
		parser.shiftToken()
		return true, nil
	} else {
		return false, parser.err()
	}
}

// Returns next token without removing it from tokens buffer
func (parser *Parser) nextToken() *scanner.Token {
	if len(parser.tokens) == 0 {
		// fetch next token
		nextToken := parser.scan.Next()

		// log.Printf("[token] %s => %v", nextToken.Type.String(), nextToken.Value)

		// queue it
		parser.tokens = append(parser.tokens, nextToken)
	}

	return parser.tokens[0]
}

// Returns next token and remove it from the tokens buffer
func (parser *Parser) shiftToken() *scanner.Token {
	var result *scanner.Token

	result, parser.tokens = parser.tokens[0], parser.tokens[1:]
	return result
}

// Returns tokenizer error, or nil if no error
func (parser *Parser) err() error {
	if parser.tokenError() {
		token := parser.nextToken()
		return errors.New(fmt.Sprintf("Tokenizer error: %s", token.String()))
	} else {
		return nil
	}
}

// Returns true if next token is Error
func (parser *Parser) tokenError() bool {
	return parser.nextToken().Type == scanner.TokenError
}

// Returns true if next token is EOF
func (parser *Parser) tokenEOF() bool {
	return parser.nextToken().Type == scanner.TokenEOF
}

// Returns true if next token is a whitespace
func (parser *Parser) tokenWS() bool {
	return parser.nextToken().Type == scanner.TokenS
}

// Returns true if next token is a comment
func (parser *Parser) tokenComment() bool {
	return parser.nextToken().Type == scanner.TokenComment
}

// Returns true if next token is a CDO or a CDC
func (parser *Parser) tokenCDOorCDC() bool {
	switch parser.nextToken().Type {
	case scanner.TokenCDO, scanner.TokenCDC:
		return true
	default:
		return false
	}
}

// Returns true if next token is ignorable
func (parser *Parser) tokenIgnorable() bool {
	return parser.tokenWS() || parser.tokenComment() || parser.tokenCDOorCDC()
}

// Returns true if next token is parsable
func (parser *Parser) tokenParsable() bool {
	return !parser.tokenEOF() && !parser.tokenError()
}

// Returns true if next token is an At Rule keyword
func (parser *Parser) tokenAtKeyword() bool {
	return parser.nextToken().Type == scanner.TokenAtKeyword
}

// Returns true if next token is given character
func (parser *Parser) tokenChar(value string) bool {
	token := parser.nextToken()
	return (token.Type == scanner.TokenChar) && (token.Value == value)
}

// Returns true if next token marks the end of a prelude
func (parser *Parser) tokenEndOfPrelude() bool {
	return parser.tokenChar(";") || parser.tokenChar("{")
}
<commit_msg>Cleanup<commit_after>package parser

import (
	"errors"
	"fmt"
	"regexp"
	"strings"

	"github.com/gorilla/css/scanner"

	"github.com/aymerick/douceur/css"
)

const (
	IMPORTANT_SUFFIX_REGEXP = `(?i)\s*!important\s*$`
)

var (
	importantRegexp *regexp.Regexp
)

type Parser struct {
	scan *scanner.Scanner // Tokenizer

	// Tokens parsed but not consumed yet
	tokens []*scanner.Token

	// Rule embedding level
	embedLevel int
}

func init() {
	importantRegexp = regexp.MustCompile(IMPORTANT_SUFFIX_REGEXP)
}

// Instanciate a new parser
func NewParser(txt string) *Parser {
	return &Parser{
		scan: scanner.New(txt),
	}
}

// Parse a whole stylesheet
func Parse(text string) (*css.Stylesheet, error) {
	result, err := NewParser(text).ParseStylesheet()
	if err != nil {
		return nil, err
	} else {
		return result, nil
	}
}

// Parse CSS declarations
func ParseDeclarations(text string) ([]*css.Declaration, error) {
	result, err := NewParser(text).ParseDeclarations()
	if err != nil {
		return nil, err
	} else {
		return result, nil
	}
}

// Parse a stylesheet
func (parser *Parser) ParseStylesheet() (*css.Stylesheet, error) {
	result := css.NewStylesheet()

	// Parse BOM
	if _, err := parser.parseBOM(); err != nil {
		return result, err
	}

	// Parse list of rules
	rules, err := parser.ParseRules()
	if err != nil {
		return result, err
	}

	result.Rules = rules

	return result, nil
}

// Parse a list of rules
func (parser *Parser) ParseRules() ([]*css.Rule, error) {
	result := []*css.Rule{}

	inBlock := false
	if parser.tokenChar("{") {
		// parsing a block of rules
		inBlock = true
		parser.embedLevel += 1

		parser.shiftToken()
	}

	for parser.tokenParsable() {
		if parser.tokenIgnorable() {
			parser.shiftToken()
		} else if parser.tokenChar("}") {
			if !inBlock {
				errMsg := fmt.Sprintf("Unexpected } character: %s", parser.nextToken().String())
				return result, errors.New(errMsg)
			}

			parser.shiftToken()
			parser.embedLevel -= 1

			// finished
			break
		} else {
			rule, err := parser.ParseRule()
			if err != nil {
				return result, err
			}

			rule.EmbedLevel = parser.embedLevel
			result = append(result, rule)
		}
	}

	return result, parser.err()
}

// Parse a rule
func (parser *Parser) ParseRule() (*css.Rule, error) {
	if parser.tokenAtKeyword() {
		return parser.parseAtRule()
	} else {
		return parser.parseQualifiedRule()
	}
}

// Parse a list of declarations
func (parser *Parser) ParseDeclarations() ([]*css.Declaration, error) {
	result := []*css.Declaration{}

	if parser.tokenChar("{") {
		parser.shiftToken()
	}

	for parser.tokenParsable() {
		if parser.tokenIgnorable() {
			parser.shiftToken()
		} else if parser.tokenChar("}") {
			// end of block
			parser.shiftToken()
			break
		} else {
			declaration, err := parser.ParseDeclaration()
			if err != nil {
				return result, err
			}

			result = append(result, declaration)
		}
	}

	return result, parser.err()
}

// Parse a declaration
func (parser *Parser) ParseDeclaration() (*css.Declaration, error) {
	result := css.NewDeclaration()
	curValue := ""

	for parser.tokenParsable() {
		if parser.tokenChar(":") {
			result.Property = strings.TrimSpace(curValue)
			curValue = ""

			parser.shiftToken()
		} else if parser.tokenChar(";") || parser.tokenChar("}") {
			if result.Property == "" {
				errMsg := fmt.Sprintf("Unexpected ; character: %s", parser.nextToken().String())
				return result, errors.New(errMsg)
			}

			if importantRegexp.MatchString(curValue) {
				result.Important = true
				curValue = importantRegexp.ReplaceAllString(curValue, "")
			}

			result.Value = strings.TrimSpace(curValue)

			if parser.tokenChar(";") {
				parser.shiftToken()
			}

			// finished
			break
		} else {
			token := parser.shiftToken()
			curValue += token.Value
		}
	}

	// log.Printf("[parsed] Declaration: %s", result.String())

	return result, parser.err()
}

// Parse an At Rule
func (parser *Parser) parseAtRule() (*css.Rule, error) {
	// parse rule name (eg: "@import")
	token := parser.shiftToken()

	result := css.NewRule(css.AT_RULE)
	result.Name = token.Value

	for parser.tokenParsable() {
		if parser.tokenChar(";") {
			parser.shiftToken()

			// finished
			break
		} else if parser.tokenChar("{") {
			if result.EmbedsRules() {
				// parse rules block
				rules, err := parser.ParseRules()
				if err != nil {
					return result, err
				}

				result.Rules = rules
			} else {
				// parse declarations block
				declarations, err := parser.ParseDeclarations()
				if err != nil {
					return result, err
				}

				result.Declarations = declarations
			}

			// finished
			break
		} else {
			// parse prelude
			prelude, err := parser.parsePrelude()
			if err != nil {
				return result, err
			}

			result.Prelude = prelude
		}
	}

	// log.Printf("[parsed] Rule: %s", result.String())

	return result, parser.err()
}

// Parse a Qualified Rule
func (parser *Parser) parseQualifiedRule() (*css.Rule, error) {
	result := css.NewRule(css.QUALIFIED_RULE)

	for parser.tokenParsable() {
		if parser.tokenChar("{") {
			if result.Prelude == "" {
				errMsg := fmt.Sprintf("Unexpected { character: %s", parser.nextToken().String())
				return result, errors.New(errMsg)
			}

			// parse declarations block
			declarations, err := parser.ParseDeclarations()
			if err != nil {
				return result, err
			}

			result.Declarations = declarations

			// finished
			break
		} else {
			// parse prelude
			prelude, err := parser.parsePrelude()
			if err != nil {
				return result, err
			}

			result.Prelude = prelude
		}
	}

	result.Selectors = strings.Split(result.Prelude, ",")
	for i, sel := range result.Selectors {
		result.Selectors[i] = strings.TrimSpace(sel)
	}

	// log.Printf("[parsed] Rule: %s", result.String())

	return result, parser.err()
}

// Parse Rule prelude
func (parser *Parser) parsePrelude() (string, error) {
	result := ""

	for parser.tokenParsable() && !parser.tokenEndOfPrelude() {
		token := parser.shiftToken()
		result += token.Value
	}

	result = strings.TrimSpace(result)

	// log.Printf("[parsed] prelude: %s", result)

	return result, parser.err()
}

// Parse BOM
func (parser *Parser) parseBOM() (bool, error) {
	if parser.nextToken().Type == scanner.TokenBOM {
		parser.shiftToken()
		return true, nil
	} else {
		return false, parser.err()
	}
}

// Returns next token without removing it from tokens buffer
func (parser *Parser) nextToken() *scanner.Token {
	if len(parser.tokens) == 0 {
		// fetch next token
		nextToken := parser.scan.Next()

		// log.Printf("[token] %s => %v", nextToken.Type.String(), nextToken.Value)

		// queue it
		parser.tokens = append(parser.tokens, nextToken)
	}

	return parser.tokens[0]
}

// Returns next token and remove it from the tokens buffer
func (parser *Parser) shiftToken() *scanner.Token {
	var result *scanner.Token

	result, parser.tokens = parser.tokens[0], parser.tokens[1:]
	return result
}

// Returns tokenizer error, or nil if no error
func (parser *Parser) err() error {
	if parser.tokenError() {
		token := parser.nextToken()
		return errors.New(fmt.Sprintf("Tokenizer error: %s", token.String()))
	} else {
		return nil
	}
}

// Returns true if next token is Error
func (parser *Parser) tokenError() bool {
	return parser.nextToken().Type == scanner.TokenError
}

// Returns true if next token is EOF
func (parser *Parser) tokenEOF() bool {
	return parser.nextToken().Type == scanner.TokenEOF
}

// Returns true if next token is a whitespace
func (parser *Parser) tokenWS() bool {
	return parser.nextToken().Type == scanner.TokenS
}

// Returns true if next token is a comment
func (parser *Parser) tokenComment() bool {
	return parser.nextToken().Type == scanner.TokenComment
}

// Returns true if next token is a CDO or a CDC
func (parser *Parser) tokenCDOorCDC() bool {
	switch parser.nextToken().Type {
	case scanner.TokenCDO, scanner.TokenCDC:
		return true
	default:
		return false
	}
}

// Returns true if next token is ignorable
func (parser *Parser) tokenIgnorable() bool {
	return parser.tokenWS() || parser.tokenComment() || parser.tokenCDOorCDC()
}

// Returns true if next token is parsable
func (parser *Parser) tokenParsable() bool {
	return !parser.tokenEOF() && !parser.tokenError()
}

// Returns true if next token is an At Rule keyword
func (parser *Parser) tokenAtKeyword() bool {
	return parser.nextToken().Type == scanner.TokenAtKeyword
}

// Returns true if next token is given character
func (parser *Parser) tokenChar(value string) bool {
	token := parser.nextToken()
	return (token.Type == scanner.TokenChar) && (token.Value == value)
}

// Returns true if next token marks the end of a prelude
func (parser *Parser) tokenEndOfPrelude() bool {
	return parser.tokenChar(";") || parser.tokenChar("{")
}
<|endoftext|>


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

package parser

import (
	"fmt"
	"github.com/andreaskoch/allmark/markdown"
	"github.com/andreaskoch/allmark/repository"
	"github.com/andreaskoch/allmark/types"
	"github.com/andreaskoch/allmark/util"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	// Lines which contain nothing but white space characters
	// or no characters at all.
	EmptyLinePattern = regexp.MustCompile(`^\s*$`)

	// Lines which a start with a hash, followed by zero or more
	// white space characters, followed by text.
	TitlePattern = regexp.MustCompile(`^#\s*([\pL\pN\p{Latin}]+.+)`)

	// Lines which start with text
	DescriptionPattern = regexp.MustCompile(`^[\pL\pN\p{Latin}]+.+`)

	// Lines which nothing but dashes
	HorizontalRulePattern = regexp.MustCompile(`^-{2,}`)

	// Lines with a "key: value" syntax
	MetaDataPattern = regexp.MustCompile(`^(\w+):\s*([\pL\pN\p{Latin}]+.+)$`)
)

func Parse(item *repository.Item) (*repository.Item, error) {
	if item.IsVirtual() {
		return parseVirtual(item)
	}

	return parsePhysical(item)
}

func parseVirtual(item *repository.Item) (*repository.Item, error) {

	if item == nil {
		return nil, fmt.Errorf("Cannot create meta data from nil.")
	}

	// get the item title
	title := filepath.Base(item.Directory())

	// create the meta data
	metaData, err := newMetaData(item)
	if err != nil {
		return nil, err
	}

	item.Title = title
	item.MetaData = metaData

	return item, nil
}

func parsePhysical(item *repository.Item) (*repository.Item, error) {

	// open the file
	file, err := os.Open(item.Path())
	if err != nil {
		return nil, fmt.Errorf("%s", err)
	}

	defer file.Close()

	// get the raw lines
	lines := util.GetLines(file)

	// parse the meta data
	fallbackItemTypeFunc := func() string {
		return getItemTypeFromFilename(item.Path())
	}

	item.MetaData, lines = parseMetaData(item, lines, fallbackItemTypeFunc)

	// parse the content
	switch itemType := item.MetaData.ItemType; itemType {
	case types.RepositoryItemType, types.DocumentItemType, types.PresentationItemType:
		{
			if success, err := parseDocumentLikeItem(item, lines); success {
				return item, nil
			} else {
				return nil, err
			}
		}
	case types.MessageItemType:
		{
			if success, err := parseMessage(item, lines); success {
				return item, nil
			} else {
				return nil, err
			}
		}
	default:
		return nil, fmt.Errorf("Item %q (type: %s) cannot be parsed.", item.Path(), itemType)
	}

	panic("Unreachable")
}

// Parse an item with a title, description and content
func parseDocumentLikeItem(item *repository.Item, lines []string) (sucess bool, err error) {

	// title
	item.Title, lines = getTitle(lines)

	// description
	item.Description, lines = getDescription(lines)

	// raw markdown content
	item.RawContent = lines

	return true, nil
}

func parseMessage(item *repository.Item, lines []string) (sucess bool, err error) {

	// raw markdown content
	item.RawContent = lines

	return true, nil
}

func getMatchingValue(lines []string, matchPattern *regexp.Regexp) (string, []string) {

	// In order to be the "matching value" the line must
	// either be empty or match the supplied pattern.
	for lineNumber, line := range lines {

		lineMatchesTitlePattern, matches := util.IsMatch(line, matchPattern)
		if lineMatchesTitlePattern {
			nextLine := getNextLinenumber(lineNumber, lines)
			return util.GetLastElement(matches), lines[nextLine:]
		}

		lineIsEmpty := EmptyLinePattern.MatchString(line)
		if !lineIsEmpty {
			break
		}
	}

	return "", lines
}

func getTitle(lines []string) (title string, remainingLines []string) {
	title, remainingLines = getMatchingValue(lines, TitlePattern)

	// cleanup the title
	title = strings.TrimSpace(title)
	title = strings.TrimSuffix(title, "#")

	return title, remainingLines
}

func getDescription(lines []string) (description string, remainingLines []string) {
	description, remainingLines = getMatchingValue(lines, DescriptionPattern)

	// cleanup the description
	description = strings.TrimSpace(description)

	return description, remainingLines
}

func getNextLinenumber(lineNumber int, lines []string) int {
	nextLine := lineNumber + 1

	if nextLine <= len(lines) {
		return nextLine
	}

	return lineNumber
}

func getItemTypeFromFilename(filenameOrPath string) string {

	if !markdown.IsMarkdownFile(filenameOrPath) {
		return types.UnknownItemType // abort if file does not have a markdown extension
	}

	extension := filepath.Ext(filenameOrPath)
	filenameWithExtension := filepath.Base(filenameOrPath)
	filename := filenameWithExtension[0:(strings.LastIndex(filenameWithExtension, extension))]

	switch strings.ToLower(filename) {
	case types.DocumentItemType:
		return types.DocumentItemType

	case types.PresentationItemType:
		return types.PresentationItemType

	case types.MessageItemType:
		return types.MessageItemType

	case types.RepositoryItemType:
		return types.RepositoryItemType

	default:
		return types.DocumentItemType
	}

	return types.UnknownItemType
}
<commit_msg>Use the folder name as the items title when no title was found in the document<commit_after>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package parser

import (
	"fmt"
	"github.com/andreaskoch/allmark/markdown"
	"github.com/andreaskoch/allmark/repository"
	"github.com/andreaskoch/allmark/types"
	"github.com/andreaskoch/allmark/util"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	// Lines which contain nothing but white space characters
	// or no characters at all.
	EmptyLinePattern = regexp.MustCompile(`^\s*$`)

	// Lines which a start with a hash, followed by zero or more
	// white space characters, followed by text.
	TitlePattern = regexp.MustCompile(`^#\s*([\pL\pN\p{Latin}]+.+)`)

	// Lines which start with text
	DescriptionPattern = regexp.MustCompile(`^[\pL\pN\p{Latin}]+.+`)

	// Lines which nothing but dashes
	HorizontalRulePattern = regexp.MustCompile(`^-{2,}`)

	// Lines with a "key: value" syntax
	MetaDataPattern = regexp.MustCompile(`^(\w+):\s*([\pL\pN\p{Latin}]+.+)$`)
)

func Parse(item *repository.Item) (*repository.Item, error) {
	if item.IsVirtual() {
		return parseVirtual(item)
	}

	return parsePhysical(item)
}

func getFallbackTitle(item *repository.Item) string {
	return filepath.Base(item.Directory())
}

func parseVirtual(item *repository.Item) (*repository.Item, error) {

	if item == nil {
		return nil, fmt.Errorf("Cannot create meta data from nil.")
	}

	// get the item title
	title := getFallbackTitle(item)

	// create the meta data
	metaData, err := newMetaData(item)
	if err != nil {
		return nil, err
	}

	item.Title = title
	item.MetaData = metaData

	return item, nil
}

func parsePhysical(item *repository.Item) (*repository.Item, error) {

	// open the file
	file, err := os.Open(item.Path())
	if err != nil {
		return nil, fmt.Errorf("%s", err)
	}

	defer file.Close()

	// get the raw lines
	lines := util.GetLines(file)

	// parse the meta data
	fallbackItemTypeFunc := func() string {
		return getItemTypeFromFilename(item.Path())
	}

	item.MetaData, lines = parseMetaData(item, lines, fallbackItemTypeFunc)

	// parse the content
	switch itemType := item.MetaData.ItemType; itemType {
	case types.RepositoryItemType, types.DocumentItemType, types.PresentationItemType:
		{
			if success, err := parseDocumentLikeItem(item, lines); success {
				return item, nil
			} else {
				return nil, err
			}
		}
	case types.MessageItemType:
		{
			if success, err := parseMessage(item, lines); success {
				return item, nil
			} else {
				return nil, err
			}
		}
	default:
		return nil, fmt.Errorf("Item %q (type: %s) cannot be parsed.", item.Path(), itemType)
	}

	panic("Unreachable")
}

// Parse an item with a title, description and content
func parseDocumentLikeItem(item *repository.Item, lines []string) (sucess bool, err error) {

	// title
	item.Title, lines = getTitle(lines)
	if item.Title == "" {
		item.Title = getFallbackTitle(item)
	}

	// description
	item.Description, lines = getDescription(lines)

	// raw markdown content
	item.RawContent = lines

	return true, nil
}

func parseMessage(item *repository.Item, lines []string) (sucess bool, err error) {

	// raw markdown content
	item.RawContent = lines

	return true, nil
}

func getMatchingValue(lines []string, matchPattern *regexp.Regexp) (string, []string) {

	// In order to be the "matching value" the line must
	// either be empty or match the supplied pattern.
	for lineNumber, line := range lines {

		lineMatchesTitlePattern, matches := util.IsMatch(line, matchPattern)
		if lineMatchesTitlePattern {
			nextLine := getNextLinenumber(lineNumber, lines)
			return util.GetLastElement(matches), lines[nextLine:]
		}

		lineIsEmpty := EmptyLinePattern.MatchString(line)
		if !lineIsEmpty {
			break
		}
	}

	return "", lines
}

func getTitle(lines []string) (title string, remainingLines []string) {
	title, remainingLines = getMatchingValue(lines, TitlePattern)

	// cleanup the title
	title = strings.TrimSpace(title)
	title = strings.TrimSuffix(title, "#")

	return title, remainingLines
}

func getDescription(lines []string) (description string, remainingLines []string) {
	description, remainingLines = getMatchingValue(lines, DescriptionPattern)

	// cleanup the description
	description = strings.TrimSpace(description)

	return description, remainingLines
}

func getNextLinenumber(lineNumber int, lines []string) int {
	nextLine := lineNumber + 1

	if nextLine <= len(lines) {
		return nextLine
	}

	return lineNumber
}

func getItemTypeFromFilename(filenameOrPath string) string {

	if !markdown.IsMarkdownFile(filenameOrPath) {
		return types.UnknownItemType // abort if file does not have a markdown extension
	}

	extension := filepath.Ext(filenameOrPath)
	filenameWithExtension := filepath.Base(filenameOrPath)
	filename := filenameWithExtension[0:(strings.LastIndex(filenameWithExtension, extension))]

	switch strings.ToLower(filename) {
	case types.DocumentItemType:
		return types.DocumentItemType

	case types.PresentationItemType:
		return types.PresentationItemType

	case types.MessageItemType:
		return types.MessageItemType

	case types.RepositoryItemType:
		return types.RepositoryItemType

	default:
		return types.DocumentItemType
	}

	return types.UnknownItemType
}
<|endoftext|>


<commit_before>package parser

import (
	"errors"
	"fmt"
	"github.com/twtiger/go-seccomp/tree"
	"go/ast"
	"go/parser"
	"go/token"
	"regexp"
	"strconv"
)

var tokenTypes = make(map[token.Token]string)
var arithmeticOps = make(map[token.Token]tree.ArithmeticType)
var comparisonOps = make(map[token.Token]tree.ComparisonType)

func buildArithmeticOps() {
	arithmeticOps[token.ADD] = tree.PLUS
	arithmeticOps[token.SUB] = tree.MINUS
	arithmeticOps[token.MUL] = tree.MULT
	arithmeticOps[token.QUO] = tree.DIV
	arithmeticOps[token.REM] = tree.MOD
	arithmeticOps[token.AND] = tree.BINAND
	arithmeticOps[token.OR] = tree.BINOR
	arithmeticOps[token.XOR] = tree.BINXOR
	arithmeticOps[token.SHL] = tree.LSH
	arithmeticOps[token.SHR] = tree.RSH
}

func buildComparisonOps() {
	comparisonOps[token.EQL] = tree.EQL
	comparisonOps[token.LSS] = tree.LT
	comparisonOps[token.GTR] = tree.GT
	comparisonOps[token.NEQ] = tree.NEQL
	comparisonOps[token.LEQ] = tree.LTE
	comparisonOps[token.GEQ] = tree.GTE
	comparisonOps[token.AND] = tree.BIT
}

func init() {
	buildArithmeticOps()
	buildComparisonOps()

	tokenTypes[token.LOR] = "booleanArguments"
	tokenTypes[token.LAND] = "booleanArguments"

	for k := range arithmeticOps {
		tokenTypes[k] = "integerArguments"
	}

	for k := range comparisonOps {
		tokenTypes[k] = "numericArguments"
	}
}

func surround(s string) string {
	return "func() { " + s + "}"
}

func parseExpression(expr string) (tree.Expression, error) {
	// fs := token.NewFileSet()
	tr, _ := parser.ParseExpr(surround(expr))
	// ast.Print(fs, tr)
	parsedtree, err := unwrapToplevel(tr)
	return parsedtree, err
}

func unwrapToplevel(x ast.Node) (tree.Expression, error) {
	switch f := x.(type) {
	case *ast.FuncLit:
		return unwrapToplevel(f.Body)
	case *ast.BlockStmt:
		return unwrapToplevel(f.List[0])
	case *ast.ExprStmt:
		return unwrapBooleanExpression(f.X)
	default:
		// panicWithInfo(x)
	}
	return nil, errors.New("Expression is invalid. Unable to parse.")
}

var argRegexpRE = regexp.MustCompile(`^arg([0-5])$`)

func identExpression(f *ast.Ident) (tree.Numeric, error) {
	if match := argRegexpRE.FindStringSubmatch(f.Name); match != nil {
		ix, _ := strconv.Atoi(match[1])
		return tree.Argument{ix}, nil
	}
	switch f.Name {
	case "true":
		return tree.BooleanLiteral{true}, nil
	case "false":
		return tree.BooleanLiteral{false}, nil
	// Handle other cases here
	default:
		return tree.Variable{f.Name}, nil
	}
	return tree.Variable{f.Name}, nil
}

func unwrapNumericExpression(x ast.Node) (tree.Numeric, error) {
	switch f := x.(type) {
	case *ast.Ident:
		// Ensure ident doesn't contain stupidness like packages and stuff
		return identExpression(f)
	case *ast.BasicLit:
		// TODO: errors here
		i, _ := strconv.Atoi(f.Value)
		return tree.NumericLiteral{uint32(i)}, nil
	case *ast.BinaryExpr:
		left, err := unwrapNumericExpression(f.X)
		right, err := unwrapNumericExpression(f.Y)
		op := arithmeticOps[f.Op]
		// TODO: handle operators we don't support here
		if err != nil {
			return nil, err
		}
		return tree.Arithmetic{Left: left, Right: right, Op: op}, nil
	case *ast.ParenExpr:
		return unwrapNumericExpression(f.X)
	case *ast.UnaryExpr:
		operand, err := unwrapNumericExpression(f.X)
		if err != nil {
			return nil, err
		}
		if f.Op == token.XOR {
			return tree.BinaryNegation{operand}, nil
		}
		// TODO: Fail in a good way here
	default:
		// panicWithInfo(x)
	}
	return nil, errors.New("Expression is invalid. Unable to parse.")
}

func panicWithInfo(x interface{}) {
	panic(fmt.Sprintf("sadness: %#v", x))
}

func takesBooleanArguments(f *ast.BinaryExpr) bool {
	return tokenTypes[f.Op] == "booleanArguments"
}

func takesNumericArguments(f *ast.BinaryExpr) bool {
	return tokenTypes[f.Op] == "numericArguments"
}

func booleanArgExpression(f *ast.BinaryExpr) (tree.Boolean, error) {
	left, err := unwrapBooleanExpression(f.X)
	right, err := unwrapBooleanExpression(f.Y)
	switch f.Op {
	case token.LOR:
		return tree.Or{Left: left, Right: right}, nil
	case token.LAND:
		return tree.And{Left: left, Right: right}, nil
	}
	return nil, err
}

func numericArgExpression(f *ast.BinaryExpr) (tree.Boolean, error) {
	cmp := comparisonOps[f.Op]
	// TODO: handle incorrect thingy here
	left, err := unwrapNumericExpression(f.X)
	right, err := unwrapNumericExpression(f.Y)
	if err != nil {
		return nil, err
	}
	return tree.Comparison{Left: left, Right: right, Op: cmp}, nil
}

func inclusionExpression(f *ast.CallExpr) (tree.Boolean, error) {
	var pos bool
	var left tree.Numeric
	var err error
	right := make([]tree.Numeric, 0)
	var val tree.Numeric

	switch p := f.Fun.(type) {
	case *ast.Ident:
		if p.Name == "in" {
			pos = true
		}
		if p.Name == "notIn" {
			pos = false
		}
	}

	switch p := f.Args[0].(type) {
	case *ast.Ident:
		left, err = identExpression(p)
	case *ast.BasicLit:
		left, err = unwrapNumericExpression(p)
	}

	for _, e := range f.Args {
		switch y := e.(type) {
		case *ast.BasicLit:
			val, err = unwrapNumericExpression(y)
			right = append(right, val)
		}
	}

	if err != nil {
		return nil, err
	}

	return tree.Inclusion{pos, left, right}, nil
}

func unwrapBooleanExpression(x ast.Node) (tree.Boolean, error) {
	switch f := x.(type) {
	case *ast.BasicLit:
		switch f.Value {
		// TODO: Handle other values here
		case "1":
			return tree.BooleanLiteral{true}, nil
		case "0":
			return tree.BooleanLiteral{false}, nil
		}
		// TODO: handle failure here
	case *ast.BinaryExpr:
		if takesBooleanArguments(f) {
			return booleanArgExpression(f)
		} else if takesNumericArguments(f) {
			return numericArgExpression(f)
		}
	case *ast.ParenExpr:
		return unwrapBooleanExpression(f.X)
	case *ast.UnaryExpr:
		operand, err := unwrapBooleanExpression(f.X)
		if err == nil {
			if f.Op == token.NOT {
				return tree.Negation{operand}, nil
			}
		}
	case *ast.CallExpr:
		return inclusionExpression(f)
	case *ast.Ident:
		return identExpression(f)
		// TODO: Fail in a good way here
	default:
		// panicWithInfo(x)
	}
	return nil, errors.New("Expression is invalid. Unable to parse.")
}
<commit_msg>Fix suggested by golint<commit_after>package parser

import (
	"errors"
	"fmt"
	"github.com/twtiger/go-seccomp/tree"
	"go/ast"
	"go/parser"
	"go/token"
	"regexp"
	"strconv"
)

var tokenTypes = make(map[token.Token]string)
var arithmeticOps = make(map[token.Token]tree.ArithmeticType)
var comparisonOps = make(map[token.Token]tree.ComparisonType)

func buildArithmeticOps() {
	arithmeticOps[token.ADD] = tree.PLUS
	arithmeticOps[token.SUB] = tree.MINUS
	arithmeticOps[token.MUL] = tree.MULT
	arithmeticOps[token.QUO] = tree.DIV
	arithmeticOps[token.REM] = tree.MOD
	arithmeticOps[token.AND] = tree.BINAND
	arithmeticOps[token.OR] = tree.BINOR
	arithmeticOps[token.XOR] = tree.BINXOR
	arithmeticOps[token.SHL] = tree.LSH
	arithmeticOps[token.SHR] = tree.RSH
}

func buildComparisonOps() {
	comparisonOps[token.EQL] = tree.EQL
	comparisonOps[token.LSS] = tree.LT
	comparisonOps[token.GTR] = tree.GT
	comparisonOps[token.NEQ] = tree.NEQL
	comparisonOps[token.LEQ] = tree.LTE
	comparisonOps[token.GEQ] = tree.GTE
	comparisonOps[token.AND] = tree.BIT
}

func init() {
	buildArithmeticOps()
	buildComparisonOps()

	tokenTypes[token.LOR] = "booleanArguments"
	tokenTypes[token.LAND] = "booleanArguments"

	for k := range arithmeticOps {
		tokenTypes[k] = "integerArguments"
	}

	for k := range comparisonOps {
		tokenTypes[k] = "numericArguments"
	}
}

func surround(s string) string {
	return "func() { " + s + "}"
}

func parseExpression(expr string) (tree.Expression, error) {
	// fs := token.NewFileSet()
	tr, _ := parser.ParseExpr(surround(expr))
	// ast.Print(fs, tr)
	parsedtree, err := unwrapToplevel(tr)
	return parsedtree, err
}

func unwrapToplevel(x ast.Node) (tree.Expression, error) {
	switch f := x.(type) {
	case *ast.FuncLit:
		return unwrapToplevel(f.Body)
	case *ast.BlockStmt:
		return unwrapToplevel(f.List[0])
	case *ast.ExprStmt:
		return unwrapBooleanExpression(f.X)
	default:
		// panicWithInfo(x)
	}
	return nil, errors.New("Expression is invalid. Unable to parse.")
}

var argRegexpRE = regexp.MustCompile(`^arg([0-5])$`)

func identExpression(f *ast.Ident) (tree.Numeric, error) {
	if match := argRegexpRE.FindStringSubmatch(f.Name); match != nil {
		ix, _ := strconv.Atoi(match[1])
		return tree.Argument{ix}, nil
	}
	switch f.Name {
	case "true":
		return tree.BooleanLiteral{true}, nil
	case "false":
		return tree.BooleanLiteral{false}, nil
	// Handle other cases here
	default:
		return tree.Variable{f.Name}, nil
	}
	return tree.Variable{f.Name}, nil
}

func unwrapNumericExpression(x ast.Node) (tree.Numeric, error) {
	switch f := x.(type) {
	case *ast.Ident:
		// Ensure ident doesn't contain stupidness like packages and stuff
		return identExpression(f)
	case *ast.BasicLit:
		// TODO: errors here
		i, _ := strconv.Atoi(f.Value)
		return tree.NumericLiteral{uint32(i)}, nil
	case *ast.BinaryExpr:
		left, err := unwrapNumericExpression(f.X)
		right, err := unwrapNumericExpression(f.Y)
		op := arithmeticOps[f.Op]
		// TODO: handle operators we don't support here
		if err != nil {
			return nil, err
		}
		return tree.Arithmetic{Left: left, Right: right, Op: op}, nil
	case *ast.ParenExpr:
		return unwrapNumericExpression(f.X)
	case *ast.UnaryExpr:
		operand, err := unwrapNumericExpression(f.X)
		if err != nil {
			return nil, err
		}
		if f.Op == token.XOR {
			return tree.BinaryNegation{operand}, nil
		}
		// TODO: Fail in a good way here
	default:
		// panicWithInfo(x)
	}
	return nil, errors.New("Expression is invalid. Unable to parse.")
}

func panicWithInfo(x interface{}) {
	panic(fmt.Sprintf("sadness: %#v", x))
}

func takesBooleanArguments(f *ast.BinaryExpr) bool {
	return tokenTypes[f.Op] == "booleanArguments"
}

func takesNumericArguments(f *ast.BinaryExpr) bool {
	return tokenTypes[f.Op] == "numericArguments"
}

func booleanArgExpression(f *ast.BinaryExpr) (tree.Boolean, error) {
	left, err := unwrapBooleanExpression(f.X)
	right, err := unwrapBooleanExpression(f.Y)
	switch f.Op {
	case token.LOR:
		return tree.Or{Left: left, Right: right}, nil
	case token.LAND:
		return tree.And{Left: left, Right: right}, nil
	}
	return nil, err
}

func numericArgExpression(f *ast.BinaryExpr) (tree.Boolean, error) {
	cmp := comparisonOps[f.Op]
	// TODO: handle incorrect thingy here
	left, err := unwrapNumericExpression(f.X)
	right, err := unwrapNumericExpression(f.Y)
	if err != nil {
		return nil, err
	}
	return tree.Comparison{Left: left, Right: right, Op: cmp}, nil
}

func inclusionExpression(f *ast.CallExpr) (tree.Boolean, error) {
	var pos bool
	var left tree.Numeric
	var err error
	var right[] tree.Numeric
	var val tree.Numeric

	switch p := f.Fun.(type) {
	case *ast.Ident:
		if p.Name == "in" {
			pos = true
		}
		if p.Name == "notIn" {
			pos = false
		}
	}

	switch p := f.Args[0].(type) {
	case *ast.Ident:
		left, err = identExpression(p)
	case *ast.BasicLit:
		left, err = unwrapNumericExpression(p)
	}

	for _, e := range f.Args {
		switch y := e.(type) {
		case *ast.BasicLit:
			val, err = unwrapNumericExpression(y)
			right = append(right, val)
		}
	}

	if err != nil {
		return nil, err
	}

	return tree.Inclusion{pos, left, right}, nil
}

func unwrapBooleanExpression(x ast.Node) (tree.Boolean, error) {
	switch f := x.(type) {
	case *ast.BasicLit:
		switch f.Value {
		// TODO: Handle other values here
		case "1":
			return tree.BooleanLiteral{true}, nil
		case "0":
			return tree.BooleanLiteral{false}, nil
		}
		// TODO: handle failure here
	case *ast.BinaryExpr:
		if takesBooleanArguments(f) {
			return booleanArgExpression(f)
		} else if takesNumericArguments(f) {
			return numericArgExpression(f)
		}
	case *ast.ParenExpr:
		return unwrapBooleanExpression(f.X)
	case *ast.UnaryExpr:
		operand, err := unwrapBooleanExpression(f.X)
		if err == nil {
			if f.Op == token.NOT {
				return tree.Negation{operand}, nil
			}
		}
	case *ast.CallExpr:
		return inclusionExpression(f)
	case *ast.Ident:
		return identExpression(f)
		// TODO: Fail in a good way here
	default:
		// panicWithInfo(x)
	}
	return nil, errors.New("Expression is invalid. Unable to parse.")
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"reflect"
	"strings"
	"testing"
)

func strRepeat(s string) string {
	return strings.Repeat(s, idSize/2)
}

func byteRepeat(b byte) []byte {
	return bytes.Repeat([]byte{b}, idSize/2)
}

func TestIDFromString(t *testing.T) {
	for _, c := range []struct {
		in      string
		want    []byte
		wantErr bool
	}{
		{"", nil, true},
		{"invalidhex", nil, true},
		{strings.Repeat("0", idSize-1), nil, true},
		{strings.Repeat("0", idSize+1), nil, true},
		{strRepeat("00"), byteRepeat(0x00), false},
		{strRepeat("01"), byteRepeat(0x01), false},
		{strRepeat("0a"), byteRepeat(0x0a), false},
		{strRepeat("0F"), byteRepeat(0x0f), false},
		{strRepeat("10"), byteRepeat(0x10), false},
		{strRepeat("ee"), byteRepeat(0xee), false},
	} {
		got, err := IDFromString(c.in)
		if c.wantErr {
			if err == nil {
				t.Errorf(`IDFromString("%s") didn't error as expected.`, c.in)
			}
		} else if !reflect.DeepEqual(got[:], c.want) {
			t.Errorf(`IDFromString("%s") got %q, want %q`, c.in, got[:], c.want)
		}
	}
}

func TestIDString(t *testing.T) {
	var id ID
	for _, c := range []struct {
		in   []byte
		want string
	}{
		{byteRepeat(0x00), strRepeat("00")},
		{byteRepeat(0xee), strRepeat("ee")},
	} {
		copy(id[:], c.in)
		got := id.String()
		if got != c.want {
			t.Errorf(`ID.String() for %q got "%s", want "%s"`, c.in, got, c.want)
		}
	}
}
<commit_msg>tests: no need to use a slice<commit_after>package main

import (
	"bytes"
	"reflect"
	"strings"
	"testing"
)

func strRepeat(s string) string {
	return strings.Repeat(s, idSize/2)
}

func byteRepeat(b byte) []byte {
	return bytes.Repeat([]byte{b}, idSize/2)
}

func TestIDFromString(t *testing.T) {
	for _, c := range [...]struct {
		in      string
		want    []byte
		wantErr bool
	}{
		{"", nil, true},
		{"invalidhex", nil, true},
		{strings.Repeat("0", idSize-1), nil, true},
		{strings.Repeat("0", idSize+1), nil, true},
		{strRepeat("00"), byteRepeat(0x00), false},
		{strRepeat("01"), byteRepeat(0x01), false},
		{strRepeat("0a"), byteRepeat(0x0a), false},
		{strRepeat("0F"), byteRepeat(0x0f), false},
		{strRepeat("10"), byteRepeat(0x10), false},
		{strRepeat("ee"), byteRepeat(0xee), false},
	} {
		got, err := IDFromString(c.in)
		if c.wantErr {
			if err == nil {
				t.Errorf(`IDFromString("%s") didn't error as expected.`, c.in)
			}
		} else if !reflect.DeepEqual(got[:], c.want) {
			t.Errorf(`IDFromString("%s") got %q, want %q`, c.in, got[:], c.want)
		}
	}
}

func TestIDString(t *testing.T) {
	var id ID
	for _, c := range []struct {
		in   []byte
		want string
	}{
		{byteRepeat(0x00), strRepeat("00")},
		{byteRepeat(0xee), strRepeat("ee")},
	} {
		copy(id[:], c.in)
		got := id.String()
		if got != c.want {
			t.Errorf(`ID.String() for %q got "%s", want "%s"`, c.in, got, c.want)
		}
	}
}
<|endoftext|>