Exemple #1
0
func TestToken_qsep_pop(t *testing.T) {
	str := `hello "world this is" a test where token 2 was quoted`
	expect := "world this is"
	fmt.Fprintf(os.Stderr, "testing: (%s)\n", str)

	ntokens, tokens := token.Tokenise_qpopulated(str, " ")
	if ntokens != 9 {
		fmt.Fprintf(os.Stderr, "FAIL: bad number of tokens, expected 9 got %d from (%s)\n", ntokens, str)
		t.Fail()
	}

	if strings.Index(tokens[1], `"`) >= 0 {
		fmt.Fprintf(os.Stderr, "FAIL: token 2 contained quotes (%s) in %s\n", tokens[1], str)
		t.Fail()
	}

	if tokens[1] != expect {
		fmt.Fprintf(os.Stderr, "FAIL: token 2 expected to be 'world this is' but was '%s'\n", tokens[1])
		t.Fail()
	}
	fmt.Fprintf(os.Stderr, "expected: '%s' found: '%s'   [OK]\n", expect, tokens[1])

	//----------------------------------------------

	str = `hello "world"` // specific test on 2014/01/13 bug fix
	expect = "world"
	fmt.Fprintf(os.Stderr, "testing: (%s)\n", str)
	ntokens, tokens = token.Tokenise_qpopulated(str, " ")
	if strings.Index(tokens[1], `"`) >= 0 {
		fmt.Fprintf(os.Stderr, "FAIL: token 2 contained quotes (%s) in (%s)\n", tokens[1], str)
		t.Fail()
	}
	if tokens[1] != expect {
		fmt.Fprintf(os.Stderr, "FAIL: token 2 expected to be 'world this is' but was '%s'\n", tokens[1])
		t.Fail()
	}
	fmt.Fprintf(os.Stderr, "expected: '%s' found: '%s got %d tokens'   [OK]\n", expect, tokens[1], ntokens)

	//----------------------------------------------
	str = `hello      "world"` // lots of spaces -- result should be same as previous; 2 tokens
	expect = "world"
	fmt.Fprintf(os.Stderr, "testing: (%s)\n", str)
	ntokens, tokens = token.Tokenise_qpopulated(str, " ")
	if ntokens != 2 {
		fmt.Fprintf(os.Stderr, "FAIL: expected 2 tokens bug %d came back\n", ntokens)
		t.Fail()
	}
	if strings.Index(tokens[1], `"`) >= 0 {
		fmt.Fprintf(os.Stderr, "FAIL: token 2 contained quotes (%s) in (%s)\n", tokens[1], str)
		t.Fail()
	}
	if tokens[1] != expect {
		fmt.Fprintf(os.Stderr, "FAIL: token 2 expected to be 'world this is' but was '%s'\n", tokens[1])
		t.Fail()
	}
	fmt.Fprintf(os.Stderr, "expected: '%s' found: '%s got %d tokens'   [OK]\n", expect, tokens[1], ntokens)

	//----------------------------------------------
}
Exemple #2
0
func Cmd2strings(cbuf string) (rdata []string, edata []string, err error) {

	ntokens, tokens := token.Tokenise_qpopulated(cbuf, " ")
	if ntokens < 1 {
		return
	}

	cmd := &exec.Cmd{} // set the command up
	cmd.Path, _ = exec.LookPath(tokens[0])
	cmd.Args = tokens
	stdout, err := cmd.StdoutPipe() // create pipes for stderr/out
	srdr := bufio.NewReader(stdout) // standard out reader

	stderr, err := cmd.StderrPipe()
	erdr := bufio.NewReader(stderr)

	err = cmd.Start()
	if err != nil {
		rdata = make([]string, 1)
		edata = make([]string, 1)
		return
	}

	rdata = make([]string, 8192)
	edata = make([]string, 8192)

	i := 0
	for {
		buf, _, err := srdr.ReadLine()
		if err != nil {
			break
		}
		if i < len(rdata) { // must read it all before calling wait, but don't overrun our buffer
			if len(buf) > 0 {
				nb := make([]byte, len(buf))
				copy(nb, buf)
				rdata[i] = string(nb)
				i++
			}
		}
	}
	if i > 0 {
		rdata = rdata[0:i] // scale back the output to just what was used
	} else {
		rdata = rdata[0:1]
	}

	i = 0
	for {
		buf, _, err := erdr.ReadLine()
		if err != nil {
			break
		}
		if i < len(edata) { // must read it all before calling wait, but don't overrun our buffer

			if len(buf) > 0 {
				nb := make([]byte, len(buf))
				copy(nb, buf)
				edata[i] = string(nb)
				i++
			}
		}
	}
	if i > 0 {
		edata = edata[0:i] // scale back the output to just what was used
	} else {
		edata = edata[0:1]
	}

	err = cmd.Wait()

	return
}
Exemple #3
0
/*
	Parses a configuration file containing sections and key/value pairs within the
	sections.  Returns a map of sections (by name) with each entry in the map being
	a map[string]interface{}.  Key/values are converted and stored by the key name as
	either string pointers or float64s.  If the value is quoted, the quotes are removed.

	Section names may be duplicated which causes values appearing later in subsequent
	sections to be added to the previously encountered values.  Keys within each section
	must be uniqueue.  If a duplicate key is encountered, the last one read will be the
	one that ends up in the map.

	If all_str is true, then all values are returned as strings; no attempt is made
	to convert values that seem to be numeric into actual values as it  might make logic
	in the user programme a bit easier (no interface dreferences).
*/
func Parse(sectmap map[string]map[string]interface{}, fname string, all_str bool) (m map[string]map[string]interface{}, err error) {
	var (
		rec   string                       // record read from input file
		sect  map[string]interface{}       // current section
		sname string                       // current section name
		rerr  error                  = nil // read error
	)

	if sectmap != nil {
		m = sectmap
		if m["default"] == nil { // don't count on user creating a default section
			m["default"] = make(map[string]interface{})
		}
	} else {
		m = make(map[string]map[string]interface{})
		m["default"] = make(map[string]interface{})
	}

	sname = "default"
	sect = m[sname] // always start in default section

	f, err := os.Open(fname)
	if err != nil {
		return
	}
	defer f.Close()

	br := bufio.NewReader(f)
	for rerr == nil {
		rec, rerr = br.ReadString('\n')
		if rerr == nil {
			rec = strings.Trim(rec, " \t\n") // ditch lead/trail whitespace

			if len(rec) == 0 { // blank line
				continue
			}

			switch rec[0] {
			case ':': // section
				//sname = rec[1:];
				_, tokens := token.Tokenise_qpopulated(rec, " \t") // easy way to ditch everything after the first token
				sname = tokens[0][1:]
				if m[sname] == nil {
					sect = make(map[string]interface{})
					m[sname] = sect
				} else {
					sect = m[sname]
				}

			case '#': // comment
				// nop

			case '<':
				m, err = Parse(m, rec[1:], all_str)
				if err != nil {
					return
				}

			default: // assume key value pair
				append := false
				first_tok := 1                              // first token of var is 1, but could be later
				force_str := strings.Index(rec, "\"") != -1 // if a quote in the buffer, we force it to be a string

				ntokens, tokens := token.Tokenise_qpopulated(rec, " \t=")
				if ntokens >= 2 { // if key = "value" # [comment],  n will be 3 or more
					tl := len(tokens[0])

					if tokens[0][tl-1:] == "+" { //foo+= bar rather than foo = bar or foo += bar
						tokens[0] = tokens[0][:tl-1]
						append = true
					} else {
						if tokens[1] == "+" { // += results in lone plus, not to be confused with +9999
							append = true
							first_tok++
						}
					}

					key := tokens[0]
					if tokens[first_tok] == "" { // key = (missing value) given
						tokens[first_tok] = " "
					}
					fc := tokens[first_tok][0:1]
					if !force_str && !all_str && ((fc >= "0" && fc <= "9") || fc == "+" || fc == "-") { // allowed to convert numbers to float
						sect[key] = clike.Atof(tokens[first_tok])
					} else {
						dup := ""
						sep := ""
						for i := first_tok; i < ntokens && tokens[i][0:1] != "#"; i++ {
							dup += sep + tokens[i] // snarf tokens up to comment reducing white space to 1 blank
							sep = " "
						}
						if append && sect[key] != nil {
							if old_str, ok := sect[key].(*string); ok {
								dup = *old_str + " " + dup
							}
						}

						sect[key] = &dup
					}
				} // silently discard token that is just a key, allowing the default to override
			}
		}
	}

	if rerr != io.EOF {
		err = rerr
	}

	return
}
Exemple #4
0
/*
	Parses a configuration file containing sections and key/value pairs within the
	sections.  Returns a map of sections (by name) with each entry in the map being
	a map[string]interface{}.  Key/values are converted and stored by the key name as
	either string pointers or float64s.  If the value is quoted, the quotes are removed.

	Section names may be duplicated which causes values appearing later in subsequent
	sections to be added to the previously encountered values.  Keys within each section
	must be uniqueue.  If a duplicate key is encountered, the last one read will be the
	one that ends up in the map.

	If all_str is true, then all values are returned as strings; no attempt is made
	to convert values that seem to be numeric into actual values as it  might make logic
	in the user programme a bit easier (no interface dreferences).
*/
func Parse(sectmap map[string]map[string]interface{}, fname string, all_str bool) (m map[string]map[string]interface{}, err error) {
	var (
		rec   string                       // record read from input file
		sect  map[string]interface{}       // current section
		sname string                       // current section name
		rerr  error                  = nil // read error
	)

	if sectmap != nil {
		m = sectmap
		if m["default"] == nil { // don't count on user creating a default section
			m["default"] = make(map[string]interface{})
		}
	} else {
		m = make(map[string]map[string]interface{})
		m["default"] = make(map[string]interface{})
	}

	sname = "default"
	sect = m[sname] // always start in default section

	f, err := os.Open(fname)
	if err != nil {
		return
	}
	defer f.Close()

	br := bufio.NewReader(f)
	for rerr == nil {
		rec, rerr = br.ReadString('\n')
		if rerr == nil {
			rec = strings.Trim(rec, " \t\n") // ditch lead/trail whitespace

			if len(rec) == 0 { // blank line
				continue
			}

			switch rec[0] {
			case ':': // section
				//sname = rec[1:];
				_, tokens := token.Tokenise_qpopulated(rec, " \t") // easy way to ditch everything after the first token
				sname = tokens[0][1:]
				if m[sname] == nil {
					sect = make(map[string]interface{})
					m[sname] = sect
				} else {
					sect = m[sname]
				}

			case '#': // comment
				// nop

			case '<':
				m, err = Parse(m, rec[1:], all_str)
				if err != nil {
					return
				}

			default: // assume key value pair
				ntokens, tokens := token.Tokenise_qpopulated(rec, " \t=")
				if ntokens >= 2 { // if key = "value" # [comment],  n will be 3 or more
					key := tokens[0]
					if tokens[1] == "" { // key = (missing value) given
						tokens[1] = " "
					}
					fc := tokens[1][0:1]
					if !all_str && ((fc >= "0" && fc <= "9") || fc == "+" || fc == "-") { // allowed to convert numbers to float
						sect[key] = clike.Atof(tokens[1])
					} else {
						dup := ""
						sep := ""
						for i := 1; i < ntokens && tokens[i][0:1] != "#"; i++ {
							dup += sep + tokens[i] // snarf tokens up to comment reducing white space to 1 blank
							sep = " "
						}
						sect[key] = &dup
					}
				} // silently discard token that is just a key, allowing the default to override
			}
		}
	}

	if rerr != io.EOF {
		err = rerr
	}

	return
}