summaryrefslogtreecommitdiffstats
path: root/runtime/string.c
blob: a44cabc1037e5a8ead084ea454d04760d8e12147 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef _STRING_C_ /* -*- linux-c -*- */
#define _STRING_C_

#include <linux/config.h>

/** @file string.c
 * @addtogroup scbuf Scratch Buffer
 * Scratch Buffer Functions.
 * The scratch buffer is for collecting output before storing in a map,
 * printing, etc. This is a per-cpu static buffer.  It is necessary because 
 * of the limited stack space available in the kernel.
 * @todo Need careful review of these to insure safety.
 * @{
 */

#ifndef STP_STRING_SIZE
#define STP_STRING_SIZE 2048
#endif

struct string {
	short len;
	short global;
	char buf[STP_STRING_SIZE];
};

static struct string _stp_string[STP_NUM_STRINGS][NR_CPUS];

typedef struct string *String;

String _stp_string_init (int num)
{
	int global = 0;
	String str;

	if (num  < 0) {
		num = -num;
		global = 1;
	}
	
	if (num >= STP_NUM_STRINGS) {
		_stp_log ("_stp_string_init internal error: requested string exceeded allocated number");
		return NULL;
	}

	if (global)
		str = &_stp_string[num][0];
	else
		str = &_stp_string[num][smp_processor_id()];

	str->global = global;
	str->len = 0;
	return str;
}


/** Sprint into the scratch buffer.
 * Like printf, except output goes into a global scratch buffer
 * which will contain the null-terminated output.
 * Safe because overflowing the buffer is not allowed.
 * Size is limited by length of scratch buffer, STP_BUF_LEN.
 *
 * @param fmt A printf-style format string followed by a 
 * variable number of args.
 * @sa _stp_scbuf_clear
 */

void _stp_sprintf (String str, const char *fmt, ...)
{
	int num;
	va_list args;
	va_start(args, fmt);
	num = vscnprintf(str->buf + str->len, STP_STRING_SIZE - str->len - 1, fmt, args);
	va_end(args);
	if (num > 0)
		str->len += num;
}

void _stp_vsprintf (String str, const char *fmt, va_list args)
{
	int num;
	num = vscnprintf(str->buf + str->len, STP_STRING_SIZE - str->len - 1, fmt, args);
	if (num > 0)
		str->len += num;
}

/** Write a string into the scratch buffer.
 * Copies a string into a global scratch buffer.
 * Safe because overflowing the buffer is not allowed.
 * Size is limited by length of scratch buffer, STP_BUF_LEN.
 * This is more efficient than using _stp_sprint().
 *
 * @param str A string.
 */

void _stp_string_cat_cstr (String str, const char *newstr)
{
	int num = strlen (newstr);
	if (num > STP_STRING_SIZE - str->len - 1)
		num = STP_STRING_SIZE - str->len - 1;
	strncpy (str->buf + str->len, newstr, num+1);
	str->len += num;
}

void _stp_string_cat_string (String str1, String str2)
{
	int num = str2->len;
	if (num > STP_STRING_SIZE - str1->len - 1)
		num = STP_STRING_SIZE - str1->len - 1;
	strncpy (str1->buf + str1->len, str2->buf, num);
	str1->len += num;
}

char * _stp_string_ptr (String str)
{
	return str->buf;
}

#define _stp_string_cat(str1, str2)					\
  ({                                                            \
	  if (__builtin_types_compatible_p (typeof (str2), char[])) {	\
		  char *x = (char *)str2;				\
		  _str_string_cat_cstr(str1,x);				\
	  } else {							\
		  String x = (String)str2;				\
		  _str_string_cat_string(str1,x);			\
	  }								\
  })

/** @} */
#endif /* _STRING_C_ */