string_io.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:6k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*
  2.  * string_io.c --
  3.  *
  4.  * This file defines C-like input/output conversion routines for strings.
  5.  *
  6.  * Copyright (c) 1998, Massimo Dal Zotto <dz@cs.unitn.it>
  7.  *
  8.  * This file is distributed under the GNU General Public License
  9.  * either version 2, or (at your option) any later version.
  10.  */
  11. #include <ctype.h>
  12. #include <string.h>
  13. #include "postgres.h"
  14. #include "utils/elog.h"
  15. #include "utils/palloc.h"
  16. #include "utils/builtins.h"
  17. #include "string_io.h"
  18. /* define this if you want to see iso-8859 characters */
  19. #define ISO8859
  20. #define MIN(x, y) ((x) < (y) ? (x) : (y))
  21. #define VALUE(char) ((char) - '0')
  22. #define DIGIT(val) ((val) + '0')
  23. #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
  24. #ifndef ISO8859
  25. #define NOTPRINTABLE(c) (!isprint(c))
  26. #else
  27. #define NOTPRINTABLE(c) (!isprint(c) && ((c) < 0xa0))
  28. #endif
  29. /*
  30.  * string_output() --
  31.  *
  32.  * This function takes a pointer to a string data and an optional
  33.  * data size and returns a printable representation of the string
  34.  * translating all escape sequences to C-like nnn or c escapes.
  35.  * The function is used by output methods of various string types.
  36.  *
  37.  * Arguments:
  38.  * data - input data (can be NULL)
  39.  * size - optional size of data. A negative value indicates
  40.  * that data is a null terminated string.
  41.  *
  42.  * Returns:
  43.  * a pointer to a new string containing the printable
  44.  * representation of data.
  45.  */
  46. char *
  47. string_output(char *data, int size)
  48. {
  49. register unsigned char c,
  50.    *p,
  51.    *r,
  52.    *result;
  53. register int l,
  54. len;
  55. if (data == NULL)
  56. {
  57. result = (char *) palloc(2);
  58. result[0] = '-';
  59. result[1] = '';
  60. return (result);
  61. }
  62. if (size < 0)
  63. size = strlen(data);
  64. /* adjust string length for escapes */
  65. len = size;
  66. for (p = data, l = size; l > 0; p++, l--)
  67. {
  68. switch (*p)
  69. {
  70. case '\':
  71. case '"':
  72. case '{':
  73. case '}':
  74. case 'b':
  75. case 'f':
  76. case 'n':
  77. case 'r':
  78. case 't':
  79. case 'v':
  80. len++;
  81. break;
  82. default:
  83. if (NOTPRINTABLE(*p))
  84. len += 3;
  85. }
  86. }
  87. len++;
  88. result = (char *) palloc(len);
  89. for (p = data, r = result, l = size; (l > 0) && (c = *p); p++, l--)
  90. {
  91. switch (c)
  92. {
  93. case '\':
  94. case '"':
  95. case '{':
  96. case '}':
  97. *r++ = '\';
  98. *r++ = c;
  99. break;
  100. case 'b':
  101. *r++ = '\';
  102. *r++ = 'b';
  103. break;
  104. case 'f':
  105. *r++ = '\';
  106. *r++ = 'f';
  107. break;
  108. case 'n':
  109. *r++ = '\';
  110. *r++ = 'n';
  111. break;
  112. case 'r':
  113. *r++ = '\';
  114. *r++ = 'r';
  115. break;
  116. case 't':
  117. *r++ = '\';
  118. *r++ = 't';
  119. break;
  120. case 'v':
  121. *r++ = '\';
  122. *r++ = 'v';
  123. break;
  124. default:
  125. if (NOTPRINTABLE(c))
  126. {
  127. *r = '\';
  128. r += 3;
  129. *r-- = DIGIT(c & 07);
  130. c >>= 3;
  131. *r-- = DIGIT(c & 07);
  132. c >>= 3;
  133. *r = DIGIT(c & 03);
  134. r += 3;
  135. }
  136. else
  137. *r++ = c;
  138. }
  139. }
  140. *r = '';
  141. return ((char *) result);
  142. }
  143. /*
  144.  * string_input() --
  145.  *
  146.  * This function accepts a C string in input and copies it into a new
  147.  * object allocated with palloc() translating all escape sequences.
  148.  * An optional header can be allocatd before the string, for example
  149.  * to hold the length of a varlena object.
  150.  * This function is not necessary for input from sql commands because
  151.  * the parser already does escape translation, all data input routines
  152.  * receive strings in internal form.
  153.  *
  154.  * Arguments:
  155.  * str - input string possibly with escapes
  156.  * size - the required size of new data. A value of 0
  157.  * indicates a variable size string, while a
  158.  * negative value indicates a variable size string
  159.  * of size not greater than this absolute value.
  160.  * hdrsize - size of an optional header to be allocated before
  161.  * the data. It must then be filled by the caller.
  162.  * rtn_size - an optional pointer to an int variable where the
  163.  * size of the new string is stored back.
  164.  *
  165.  * Returns:
  166.  * a pointer to the new string or the header.
  167.  */
  168. char *
  169. string_input(char *str, int size, int hdrsize, int *rtn_size)
  170. {
  171. register unsigned char *p,
  172.    *r;
  173. unsigned char *result;
  174. int len;
  175. if ((str == NULL) || (hdrsize < 0))
  176. return (char *) NULL;
  177. /* Compute result size */
  178. len = strlen(str);
  179. for (p = str; *p;)
  180. {
  181. if (*p++ == '\')
  182. {
  183. if (ISOCTAL(*p))
  184. {
  185. if (ISOCTAL(*(p + 1)))
  186. {
  187. p++;
  188. len--;
  189. }
  190. if (ISOCTAL(*(p + 1)))
  191. {
  192. p++;
  193. len--;
  194. }
  195. }
  196. if (*p)
  197. p++;
  198. len--;
  199. }
  200. }
  201. /* result has variable length */
  202. if (size == 0)
  203. size = len + 1;
  204. else
  205. /* result has variable length with maximum size */
  206. if (size < 0)
  207. size = MIN(len, -size) + 1;
  208. result = (char *) palloc(hdrsize + size);
  209. memset(result, 0, hdrsize + size);
  210. if (rtn_size)
  211. *rtn_size = size;
  212. r = result + hdrsize;
  213. for (p = str; *p;)
  214. {
  215. register unsigned char c;
  216. if ((c = *p++) == '\')
  217. {
  218. switch (c = *p++)
  219. {
  220. case '':
  221. p--;
  222. break;
  223. case '0':
  224. case '1':
  225. case '2':
  226. case '3':
  227. case '4':
  228. case '5':
  229. case '6':
  230. case '7':
  231. c = VALUE(c);
  232. if (isdigit(*p))
  233. c = (c << 3) + VALUE(*p++);
  234. if (isdigit(*p))
  235. c = (c << 3) + VALUE(*p++);
  236. *r++ = c;
  237. break;
  238. case 'b':
  239. *r++ = 'b';
  240. break;
  241. case 'f':
  242. *r++ = 'f';
  243. break;
  244. case 'n':
  245. *r++ = 'n';
  246. break;
  247. case 'r':
  248. *r++ = 'r';
  249. break;
  250. case 't':
  251. *r++ = 't';
  252. break;
  253. case 'v':
  254. *r++ = 'v';
  255. break;
  256. default:
  257. *r++ = c;
  258. }
  259. }
  260. else
  261. *r++ = c;
  262. }
  263. return ((char *) result);
  264. }
  265. char *
  266. c_charout(int32 c)
  267. {
  268. char str[2];
  269. str[0] = (char) c;
  270. str[1] = '';
  271. return (string_output(str, 1));
  272. }
  273. /*
  274.  * This can be used for SET, bytea, text and unknown data types
  275.  */
  276. char *
  277. c_textout(struct varlena * vlena)
  278. {
  279. int len = 0;
  280. char    *s = NULL;
  281. if (vlena)
  282. {
  283. len = VARSIZE(vlena) - VARHDRSZ;
  284. s = VARDATA(vlena);
  285. }
  286. return (string_output(s, len));
  287. }
  288. /*
  289.  * This can be used for varchar and bpchar strings
  290.  */
  291. char *
  292. c_varcharout(char *s)
  293. {
  294. int len = 0;
  295. if (s)
  296. {
  297. len = *(int32 *) s - 4;
  298. s += 4;
  299. }
  300. return (string_output(s, len));
  301. }
  302. #if 0
  303. struct varlena *
  304. c_textin(char *str)
  305. {
  306. struct varlena *result;
  307. int len;
  308. if (str == NULL)
  309. return ((struct varlena *) NULL);
  310. result = (struct varlena *) string_input(str, 0, VARHDRSZ, &len);
  311. VARSIZE(result) = len;
  312. return (result);
  313. }
  314. int32 *
  315. c_charin(char *str)
  316. {
  317. return (string_input(str, 1, 0, NULL));
  318. }
  319. #endif
  320. /* end of file */
  321. /*
  322.  * Local Variables:
  323.  *  tab-width: 4
  324.  *  c-indent-level: 4
  325.  *  c-basic-offset: 4
  326.  * End:
  327.  */