Пример #1
0
func readLine(data *[]byte, pattern *regexp.Regexp) ([]string, error) {
	if len(*data) == 0 {
		return nil, io.EOF
	}
	indexes := pattern.FindSubmatchIndex(*data)
	if indexes == nil {
		log.Println(len(*data), string((*data)[:200]))
		return nil, ErrLineNotFound
	} else if indexes[0] != 0 {
		log.Println(indexes)
		// fmt.Println(string((*data)[:indexes[len(indexes)-1]]))
		nl := bytes.IndexAny(*data, "\r\n")
		if nl == -1 && nl+2 < len(*data) {
			return nil, ErrGarbageData
		}
		*data = (*data)[nl+1:]
		return readLine(data, pattern)
	}
	parts := make([]string, len(indexes)/2-1)
	for i := 2; i < len(indexes); i += 2 {
		parts[i/2-1] = string((*data)[indexes[i]:indexes[i+1]])
	}
	*data = (*data)[indexes[1]:]
	return parts, nil
}
Пример #2
0
func (t *transportBasicIO) WaitForRegexp(re *regexp.Regexp) ([]byte, [][]byte, error) {
	var matches [][]byte
	out, err := t.WaitForFunc(func(buf []byte) (int, error) {
		loc := re.FindSubmatchIndex(buf)
		if loc != nil {
			for i := 2; i < len(loc); i += 2 {
				matches = append(matches, buf[loc[i]:loc[i+1]])
			}
			return loc[1], nil
		}
		return -1, nil
	})
	return out, matches, err
}
Пример #3
0
// getDate parses out a date from a git header (or blob with a header
// following the size and null byte). It returns the date and index
// that the unix seconds begins at within h.
func getDate(h []byte, rx *regexp.Regexp) (d date, idx int) {
	m := rx.FindSubmatchIndex(h)
	if m == nil {
		log.Fatalf("Failed to match %s in %q", rx, h)
	}
	v := string(h[m[2]:m[3]])
	space := strings.Index(v, " ")
	if space < 0 {
		log.Fatalf("unexpected date %q", v)
	}
	n, err := strconv.ParseInt(v[:space], 10, 64)
	if err != nil {
		log.Fatalf("unexpected date %q", v)
	}
	return date{n, v[space+1:]}, m[2]
}
Пример #4
0
func replaceAll(src []byte, re *regexp.Regexp, replace func(out, src []byte, m []int) []byte) []byte {
	var out []byte
	for len(src) > 0 {
		m := re.FindSubmatchIndex(src)
		if m == nil {
			break
		}
		out = append(out, src[:m[0]]...)
		out = replace(out, src, m)
		src = src[m[1]:]
	}
	if out == nil {
		return src
	}
	return append(out, src...)
}
Пример #5
0
// findTitleMatch returns the start of the match and the "title" subgroup of
// bytes. If the regexp doesn't match, it will return -1 and nil.
func findTitleMatch(titleRE *regexp.Regexp, input []byte) (start int, title []byte) {
	indices := titleRE.FindSubmatchIndex(input)
	if len(indices) == 0 {
		return -1, nil
	}

	for i, name := range titleRE.SubexpNames() {
		if name == "title" {
			start, end := indices[2*i], indices[2*i+1]
			return indices[0], input[start:end]
		}
	}

	// there was no grouped named title
	return -1, nil
}
Пример #6
0
func (exp *Expect) checkForMatch(pat *regexp.Regexp) (m Match, found bool) {

	matches := pat.FindSubmatchIndex(exp.buffer)
	if matches != nil {
		found = true
		groupCount := len(matches) / 2
		m.Groups = make([]string, groupCount)

		for i := 0; i < groupCount; i++ {
			start := matches[2*i]
			end := matches[2*i+1]
			if start >= 0 && end >= 0 {
				m.Groups[i] = string(exp.buffer[start:end])
			}
		}
		m.Before = string(exp.buffer[0:matches[0]])
		exp.buffer = exp.buffer[matches[1]:]
	}
	return
}
Пример #7
0
func (exp *Expect) checkForMatch(expr *regexp.Regexp) bool {
	exp.locker.Lock()
	matches := expr.FindSubmatchIndex(exp.buffer)
	defer exp.locker.Unlock()
	if matches != nil {
		groupCount := len(matches) / 2
		exp.Groups = make([]string, groupCount)

		for i := 0; i < groupCount; i++ {
			start := matches[2*i]
			end := matches[2*i+1]
			if start >= 0 && end >= 0 {
				exp.Groups[i] = string(exp.buffer[start:end])
			}
		}
		exp.Before = string(exp.buffer[0:matches[0]])
		exp.buffer = exp.buffer[matches[1]:]
		return true
	}

	return false
}
Пример #8
0
func cutAllSubmatch(r *regexp.Regexp, b []byte, n int) []byte {
	i := r.FindSubmatchIndex(b)
	return bytesCut(b, i[2*n], i[2*n+1])
}
Пример #9
0
func (c *CssCompressor) performGeneralCleanup() {
	// This function does a lot, ok?
	var sb bytes.Buffer
	var previousIndex int
	var re *regexp.Regexp

	// Remove the spaces before the things that should not have spaces before them.
	// But, be careful not to turn "p :link {...}" into "p:link{...}"
	// Swap out any pseudo-class colons with the token, and then swap back.
	c.Css = RegexFindReplace(c.Css,
		"(^|\\})(([^\\{:])+:)+([^\\{]*\\{)",
		func(groups []string) string {
			s := groups[0]
			s = strings.Replace(s, ":", "___YUICSSMIN_PSEUDOCLASSCOLON___", -1)
			s = strings.Replace(s, "\\\\", "\\\\\\\\", -1)
			s = strings.Replace(s, "\\$", "\\\\\\$", -1)
			return s
		})

	// Remove spaces before the things that should not have spaces before them.
	re, _ = regexp.Compile("\\s+([!{};:>+\\(\\)\\],])")
	c.Css = re.ReplaceAll(c.Css, []byte("$1"))
	// Restore spaces for !important
	c.Css = bytes.Replace(c.Css, []byte("!important"), []byte(" !important"), -1)
	// bring back the colon
	c.Css = bytes.Replace(c.Css, []byte("___YUICSSMIN_PSEUDOCLASSCOLON___"), []byte(":"), -1)

	// retain space for special IE6 cases
	c.Css = RegexFindReplace(c.Css,
		"(?i):first\\-(line|letter)(\\{|,)",
		func(groups []string) string {
			return strings.ToLower(":first-"+groups[1]) + " " + groups[2]
		})

	// no space after the end of a preserved comment
	c.Css = bytes.Replace(c.Css, []byte("*/ "), []byte("*/"), -1)

	// If there are multiple @charset directives, push them to the top of the file.
	c.Css = RegexFindReplace(c.Css,
		"(?i)^(.*)(@charset)( \"[^\"]*\";)",
		func(groups []string) string {
			return strings.ToLower(groups[2]) + groups[3] + groups[1]
		})

	// When all @charset are at the top, remove the second and after (as they are completely ignored).
	c.Css = RegexFindReplace(c.Css,
		"(?i)^((\\s*)(@charset)( [^;]+;\\s*))+",
		func(groups []string) string {
			return groups[2] + strings.ToLower(groups[3]) + groups[4]
		})

	// lowercase some popular @directives
	c.Css = RegexFindReplace(c.Css,
		"(?i)@(charset|font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframe|media|page|namespace)",
		func(groups []string) string {
			return "@" + strings.ToLower(groups[1])
		})

	// lowercase some more common pseudo-elements
	c.Css = RegexFindReplace(c.Css,
		"(?i):(active|after|before|checked|disabled|empty|enabled|first-(?:child|of-type)|focus|hover|last-(?:child|of-type)|link|only-(?:child|of-type)|root|:selection|target|visited)",
		func(groups []string) string {
			return ":" + strings.ToLower(groups[1])
		})

	// lowercase some more common functions
	c.Css = RegexFindReplace(c.Css,
		"(?i):(lang|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|(?:-(?:moz|webkit)-)?any)\\(",
		func(groups []string) string {
			return ":" + strings.ToLower(groups[1]) + "("
		})

	// lower case some common function that can be values
	// NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us right after this
	c.Css = RegexFindReplace(c.Css,
		"(?i)([:,\\( ]\\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)",
		func(groups []string) string {
			return groups[1] + strings.ToLower(groups[2])
		})

	// Put the space back in some cases, to support stuff like
	// @media screen and (-webkit-min-device-pixel-ratio:0){
	re, _ = regexp.Compile("(?i)\\band\\(")
	c.Css = re.ReplaceAll(c.Css, []byte("and ("))

	// Remove the spaces after the things that should not have spaces after them.
	re, _ = regexp.Compile("([!{}:;>+\\(\\[,])\\s+")
	c.Css = re.ReplaceAll(c.Css, []byte("$1"))

	// remove unnecessary semicolons
	re, _ = regexp.Compile(";+}")
	c.Css = re.ReplaceAll(c.Css, []byte("}"))

	// Replace 0(px,em,%) with 0.
	re, _ = regexp.Compile("(?i)(^|[^0-9])(?:0?\\.)?0(?:px|em|%|in|cm|mm|pc|pt|ex|deg|g?rad|m?s|k?hz)")
	c.Css = re.ReplaceAll(c.Css, []byte("${1}0"))

	// Replace 0 0 0 0; with 0.
	re, _ = regexp.Compile(":0 0 0 0(;|})")
	re2, _ := regexp.Compile(":0 0 0(;|})")
	re3, _ := regexp.Compile(":0 0(;|})")
	c.Css = re.ReplaceAll(c.Css, []byte(":0$1"))
	c.Css = re2.ReplaceAll(c.Css, []byte(":0$1"))
	c.Css = re3.ReplaceAll(c.Css, []byte(":0$1"))

	// Replace background-position:0; with background-position:0 0;
	// same for transform-origin
	c.Css = RegexFindReplace(c.Css,
		"(?i)(background-position|webkit-mask-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|})",
		func(groups []string) string {
			return strings.ToLower(groups[1]) + ":0 0" + groups[2]
		})

	// Replace 0.6 to .6, but only when preceded by : or a white-space
	re, _ = regexp.Compile("(:|\\s)0+\\.(\\d+)")
	c.Css = re.ReplaceAll(c.Css, []byte("$1.$2"))

	// Shorten colors from rgb(51,102,153) to #336699
	// This makes it more likely that it'll get further compressed in the next step.
	c.Css = RegexFindReplace(c.Css,
		"rgb\\s*\\(\\s*([0-9,\\s]+)\\s*\\)",
		func(groups []string) string {
			rgbcolors := strings.Split(groups[1], ",")
			var hexcolor bytes.Buffer
			hexcolor.WriteString("#")
			for _, colour := range rgbcolors {
				val, _ := strconv.Atoi(colour)
				if val < 16 {
					hexcolor.WriteString("0")
				}
				// If someone passes an RGB value that's too big to express in two characters, round down.
				// Probably should throw out a warning here, but generating valid CSS is a bigger concern.
				if val > 255 {
					val = 255
				}
				hexcolor.WriteString(fmt.Sprintf("%x", val))
			}
			return hexcolor.String()
		})

	// Shorten colors from #AABBCC to #ABC. Note that we want to make sure
	// the color is not preceded by either ", " or =. Indeed, the property
	//     filter: chroma(color="#FFFFFF");
	// would become
	//     filter: chroma(color="#FFF");
	// which makes the filter break in IE.
	// We also want to make sure we're only compressing #AABBCC patterns inside { }, not id selectors ( #FAABAC {} )
	// We also want to avoid compressing invalid values (e.g. #AABBCCD to #ABCD)
	sb.Reset()
	re, _ = regexp.Compile("(\\=\\s*?[\"']?)?" + "#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])" + "(:?\\}|[^0-9a-fA-F{][^{]*?\\})")
	previousIndex = 0

	for match := re.Find(c.Css[previousIndex:]); match != nil; match = re.Find(c.Css[previousIndex:]) {
		index := re.FindIndex(c.Css[previousIndex:])
		submatches := re.FindStringSubmatch(string(c.Css[previousIndex:]))
		submatchIndexes := re.FindSubmatchIndex(c.Css[previousIndex:])

		sb.WriteString(string(c.Css[previousIndex : index[0]+len(c.Css[:previousIndex])]))

		//boolean isFilter = (m.group(1) != null && !"".equals(m.group(1)));
		// I hope the below is the equivalent of the above :P
		isFilter := submatches[1] != "" && submatchIndexes[1] != -1

		if isFilter {
			// Restore, as is. Compression will break filters
			sb.WriteString(submatches[1] + "#" + submatches[2] + submatches[3] + submatches[4] + submatches[5] + submatches[6] + submatches[7])
		} else {
			if strings.ToLower(submatches[2]) == strings.ToLower(submatches[3]) &&
				strings.ToLower(submatches[4]) == strings.ToLower(submatches[5]) &&
				strings.ToLower(submatches[6]) == strings.ToLower(submatches[7]) {
				// #AABBCC pattern
				sb.WriteString("#" + strings.ToLower(submatches[3]+submatches[5]+submatches[7]))
			} else {
				// Non-compressible color, restore, but lower case.
				sb.WriteString("#" + strings.ToLower(submatches[2]+submatches[3]+submatches[4]+submatches[5]+submatches[6]+submatches[7]))
			}
		}

		// The "+ 4" below is a crazy hack which will come back to haunt me later.
		// For now, it makes everything work 100%.
		previousIndex = submatchIndexes[7] + len(c.Css[:previousIndex]) + 4

	}
	if previousIndex > 0 {
		sb.WriteString(string(c.Css[previousIndex:]))
	}
	if sb.Len() > 0 {
		c.Css = sb.Bytes()
	}

	// Save a few chars by utilizing short colour keywords.
	// https://github.com/yui/yuicompressor/commit/fe8cf35d3693910103d65bf465d33b0d602dcfea
	colours := map[string]string{
		"#f00":    "red",
		"#000080": "navy",
		"#808080": "gray",
		"#808000": "olive",
		"#800080": "purple",
		"#c0c0c0": "silver",
		"#008080": "teal",
		"#ffa500": "orange",
		"#800000": "maroon",
	}
	for k, v := range colours {
		re, _ = regexp.Compile("(:|\\s)" + k + "(;|})")
		c.Css = re.ReplaceAll(c.Css, []byte("${1}"+v+"${2}"))
	}

	// border: none -> border:0
	c.Css = RegexFindReplace(c.Css,
		"(?i)(border|border-top|border-right|border-bottom|border-left|outline|background):none(;|})",
		func(groups []string) string {
			return strings.ToLower(groups[1]) + ":0" + groups[2]
		})

	// shorter opacity IE filter
	re, _ = regexp.Compile("(?i)progid:DXImageTransform.Microsoft.Alpha\\(Opacity=")
	c.Css = re.ReplaceAll(c.Css, []byte("alpha(opacity="))

	// Find a fraction that is used for Opera's -o-device-pixel-ratio query
	// Add token to add the "\" back in later
	re, _ = regexp.Compile("\\(([\\-A-Za-z]+):([0-9]+)\\/([0-9]+)\\)")
	c.Css = re.ReplaceAll(c.Css, []byte("(${1}:${2}___YUI_QUERY_FRACTION___${3})"))

	// Remove empty rules.
	re, _ = regexp.Compile("[^\\}\\{/;]+\\{\\}")
	c.Css = re.ReplaceAll(c.Css, []byte(""))

	// Add "\" back to fix Opera -o-device-pixel-ratio query
	c.Css = bytes.Replace(c.Css, []byte("___YUI_QUERY_FRACTION___"), []byte("/"), -1)
}