Blame view

tools/perf/util/strbuf.c 2.91 KB
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
1
  #include "debug.h"
7ed0958ae   Arnaldo Carvalho de Melo   perf strbuf: Add ...
2
  #include "util.h"
e7f01d1e3   Arnaldo Carvalho de Melo   perf tools: Use s...
3
  #include <linux/kernel.h>
a43783aee   Arnaldo Carvalho de Melo   perf tools: Inclu...
4
  #include <errno.h>
078006012   Ingo Molnar   perf_counter tool...
5

078006012   Ingo Molnar   perf_counter tool...
6
7
8
9
10
11
  /*
   * Used as the default ->buf value, so that people can always assume
   * buf is non NULL and ->buf is NUL terminated even for a freshly
   * initialized strbuf.
   */
  char strbuf_slopbuf[1];
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
12
  int strbuf_init(struct strbuf *sb, ssize_t hint)
078006012   Ingo Molnar   perf_counter tool...
13
14
15
16
  {
  	sb->alloc = sb->len = 0;
  	sb->buf = strbuf_slopbuf;
  	if (hint)
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
17
18
  		return strbuf_grow(sb, hint);
  	return 0;
078006012   Ingo Molnar   perf_counter tool...
19
20
21
22
23
  }
  
  void strbuf_release(struct strbuf *sb)
  {
  	if (sb->alloc) {
74cf249d5   Arnaldo Carvalho de Melo   perf tools: Use z...
24
  		zfree(&sb->buf);
078006012   Ingo Molnar   perf_counter tool...
25
26
27
28
29
30
31
32
33
34
35
36
  		strbuf_init(sb, 0);
  	}
  }
  
  char *strbuf_detach(struct strbuf *sb, size_t *sz)
  {
  	char *res = sb->alloc ? sb->buf : NULL;
  	if (sz)
  		*sz = sb->len;
  	strbuf_init(sb, 0);
  	return res;
  }
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
37
  int strbuf_grow(struct strbuf *sb, size_t extra)
078006012   Ingo Molnar   perf_counter tool...
38
  {
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  	char *buf;
  	size_t nr = sb->len + extra + 1;
  
  	if (nr < sb->alloc)
  		return 0;
  
  	if (nr <= sb->len)
  		return -E2BIG;
  
  	if (alloc_nr(sb->alloc) > nr)
  		nr = alloc_nr(sb->alloc);
  
  	/*
  	 * Note that sb->buf == strbuf_slopbuf if sb->alloc == 0, and it is
  	 * a static variable. Thus we have to avoid passing it to realloc.
  	 */
  	buf = realloc(sb->alloc ? sb->buf : NULL, nr * sizeof(*buf));
  	if (!buf)
  		return -ENOMEM;
  
  	sb->buf = buf;
  	sb->alloc = nr;
  	return 0;
078006012   Ingo Molnar   perf_counter tool...
62
  }
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
63
  int strbuf_addch(struct strbuf *sb, int c)
0741208a7   Arnaldo Carvalho de Melo   perf tools: Unexp...
64
  {
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
65
66
67
  	int ret = strbuf_grow(sb, 1);
  	if (ret)
  		return ret;
0741208a7   Arnaldo Carvalho de Melo   perf tools: Unexp...
68
69
  	sb->buf[sb->len++] = c;
  	sb->buf[sb->len] = '\0';
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
70
  	return 0;
0741208a7   Arnaldo Carvalho de Melo   perf tools: Unexp...
71
  }
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
72
  int strbuf_add(struct strbuf *sb, const void *data, size_t len)
078006012   Ingo Molnar   perf_counter tool...
73
  {
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
74
75
76
  	int ret = strbuf_grow(sb, len);
  	if (ret)
  		return ret;
078006012   Ingo Molnar   perf_counter tool...
77
  	memcpy(sb->buf + sb->len, data, len);
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
78
  	return strbuf_setlen(sb, sb->len + len);
078006012   Ingo Molnar   perf_counter tool...
79
  }
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
80
  static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
078006012   Ingo Molnar   perf_counter tool...
81
  {
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
82
  	int len, ret;
c71183697   Namhyung Kim   perf tools: Intro...
83
  	va_list ap_saved;
078006012   Ingo Molnar   perf_counter tool...
84

5cea57f30   Masami Hiramatsu   perf tools: Rewri...
85
86
87
88
89
  	if (!strbuf_avail(sb)) {
  		ret = strbuf_grow(sb, 64);
  		if (ret)
  			return ret;
  	}
c71183697   Namhyung Kim   perf tools: Intro...
90
91
  
  	va_copy(ap_saved, ap);
f787d9519   Namhyung Kim   perf tools: Fix s...
92
  	len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
078006012   Ingo Molnar   perf_counter tool...
93
  	if (len < 0)
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
94
  		return len;
078006012   Ingo Molnar   perf_counter tool...
95
  	if (len > strbuf_avail(sb)) {
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
96
97
98
  		ret = strbuf_grow(sb, len);
  		if (ret)
  			return ret;
c71183697   Namhyung Kim   perf tools: Intro...
99
100
  		len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
  		va_end(ap_saved);
078006012   Ingo Molnar   perf_counter tool...
101
  		if (len > strbuf_avail(sb)) {
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
102
103
  			pr_debug("this should not happen, your vsnprintf is broken");
  			return -EINVAL;
078006012   Ingo Molnar   perf_counter tool...
104
105
  		}
  	}
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
106
  	return strbuf_setlen(sb, sb->len + len);
078006012   Ingo Molnar   perf_counter tool...
107
  }
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
108
  int strbuf_addf(struct strbuf *sb, const char *fmt, ...)
c71183697   Namhyung Kim   perf tools: Intro...
109
110
  {
  	va_list ap;
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
111
  	int ret;
c71183697   Namhyung Kim   perf tools: Intro...
112
113
  
  	va_start(ap, fmt);
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
114
  	ret = strbuf_addv(sb, fmt, ap);
c71183697   Namhyung Kim   perf tools: Intro...
115
  	va_end(ap);
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
116
  	return ret;
c71183697   Namhyung Kim   perf tools: Intro...
117
  }
f37a291c5   Ingo Molnar   perf_counter tool...
118
  ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
078006012   Ingo Molnar   perf_counter tool...
119
120
121
  {
  	size_t oldlen = sb->len;
  	size_t oldalloc = sb->alloc;
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
122
123
124
125
126
  	int ret;
  
  	ret = strbuf_grow(sb, hint ? hint : 8192);
  	if (ret)
  		return ret;
078006012   Ingo Molnar   perf_counter tool...
127

078006012   Ingo Molnar   perf_counter tool...
128
129
130
131
132
133
134
135
136
  	for (;;) {
  		ssize_t cnt;
  
  		cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
  		if (cnt < 0) {
  			if (oldalloc == 0)
  				strbuf_release(sb);
  			else
  				strbuf_setlen(sb, oldlen);
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
137
  			return cnt;
078006012   Ingo Molnar   perf_counter tool...
138
139
140
141
  		}
  		if (!cnt)
  			break;
  		sb->len += cnt;
5cea57f30   Masami Hiramatsu   perf tools: Rewri...
142
143
144
  		ret = strbuf_grow(sb, 8192);
  		if (ret)
  			return ret;
078006012   Ingo Molnar   perf_counter tool...
145
146
147
148
149
  	}
  
  	sb->buf[sb->len] = '\0';
  	return sb->len - oldlen;
  }