Graphviz  2.41.20170921.2350
io.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include <stdio.h>
15 #include <cghdr.h>
16 #if defined(_WIN32)
17 #include <io.h>
18 #endif
19 
20 /* experimental ICONV code - probably should be removed - JCE */
21 #undef HAVE_ICONV
22 
23 #ifdef HAVE_ICONV
24 #include <iconv.h>
25 #include <langinfo.h>
26 #include <errno.h>
27 #endif
28 
29 #ifdef HAVE_ICONV
30 static int iofreadiconv(void *chan, char *buf, int bufsize)
31 {
32 #define CHARBUFSIZE 30
33  static char charbuf[CHARBUFSIZE];
34  static iconv_t cd = NULL;
35  char *inbuf, *outbuf, *readbuf;
36  size_t inbytesleft, outbytesleft, readbytesleft, resbytes, result;
37  int fd;
38 
39  if (!cd) {
40  cd = iconv_open(nl_langinfo(CODESET), "UTF-8");
41  }
42  fd = fileno((FILE *) chan);
43  readbuf = inbuf = charbuf;
44  readbytesleft = CHARBUFSIZE;
45  inbytesleft = 0;
46  outbuf = buf;
47  outbytesleft = bufsize - 1;
48  while (1) {
49  if ((result = read(fd, readbuf++, 1)) != 1)
50  break;
51  readbytesleft--;
52  inbytesleft++;
53  result = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
54  if (result != -1) {
55  readbuf = inbuf = charbuf;
56  readbytesleft = CHARBUFSIZE;
57  inbytesleft = 0;
58  } else if (errno != EINVAL)
59  break;
60  }
61  *outbuf = '\0';
62  resbytes = bufsize - 1 - outbytesleft;
63  if (resbytes)
64  result = resbytes;
65  return result;
66 }
67 #endif
68 
69 static int iofread(void *chan, char *buf, int bufsize)
70 {
71  if (fgets(buf, bufsize, (FILE*)chan))
72  return strlen(buf);
73  else
74  return 0;
75  /* return read(fileno((FILE *) chan), buf, bufsize); */
76  /* return fread(buf, 1, bufsize, (FILE*)chan); */
77 }
78 
79 /* default IO methods */
80 static int ioputstr(void *chan, const char *str)
81 {
82  return fputs(str, (FILE *) chan);
83 }
84 
85 static int ioflush(void *chan)
86 {
87  return fflush((FILE *) chan);
88 }
89 
90 /* Agiodisc_t AgIoDisc = { iofreadiconv, ioputstr, ioflush }; */
91 Agiodisc_t AgIoDisc = { iofread, ioputstr, ioflush };
92 
93 typedef struct {
94  const char *data;
95  int len;
96  int cur;
97 } rdr_t;
98 
99 static int
100 memiofread(void *chan, char *buf, int bufsize)
101 {
102  const char *ptr;
103  char *optr;
104  char c;
105  int l;
106  rdr_t *s;
107 
108  if (bufsize == 0) return 0;
109  s = (rdr_t *) chan;
110  if (s->cur >= s->len)
111  return 0;
112  l = 0;
113  ptr = s->data + s->cur;
114  optr = buf;
115  /* We know we have at least one character */
116  c = *ptr++;
117  do {
118  *optr++ = c;
119  l++;
120  /* continue if c is not newline, we have space in buffer,
121  * and next character is non-null (we are working with
122  * null-terminated strings.
123  */
124  } while ((c != '\n') && (l < bufsize) && (c = *ptr++));
125  s->cur += l;
126  return l;
127 }
128 
129 static Agiodisc_t memIoDisc = {memiofread, 0, 0};
130 
131 Agraph_t *agmemread(const char *cp)
132 {
133  Agraph_t* g;
134  rdr_t rdr;
135  Agdisc_t disc;
136 
137  memIoDisc.putstr = AgIoDisc.putstr;
138  memIoDisc.flush = AgIoDisc.flush;
139  rdr.data = cp;
140  rdr.len = strlen(cp);
141  rdr.cur = 0;
142 
143  disc.mem = &AgMemDisc;
144  disc.id = &AgIdDisc;
145  disc.io = &memIoDisc;
146  g = agread (&rdr, &disc);
147  /* Null out filename and reset line number
148  * The name may have been set with a ppDirective, and
149  * we want to reset line_num.
150  */
151  agsetfile(NULL);
152  return g;
153 }
154 
Agiddisc_t * id
Definition: cgraph.h:191
CGRAPH_API Agmemdisc_t AgMemDisc
Definition: cgraph.h:197
CGRAPH_API Agiodisc_t AgIoDisc
Definition: cgraph.h:199
CGRAPH_API void agsetfile(char *)
Definition: scan.c:573
Definition: io.c:93
CGRAPH_API Agraph_t * agread(void *chan, Agdisc_t *disc)
Definition: grammar.c:2349
CGRAPH_API Agiddisc_t AgIdDisc
Definition: cgraph.h:198
Agmemdisc_t * mem
Definition: cgraph.h:190
int len
Definition: io.c:95
CGRAPH_API Agraph_t * agmemread(const char *cp)
Definition: io.c:131
int(* flush)(void *chan)
Definition: cgraph.h:185
int cur
Definition: io.c:96
const char * data
Definition: io.c:94
Definition: grammar.c:79
#define NULL
Definition: logic.h:39
Agiodisc_t * io
Definition: cgraph.h:192
agxbuf * str
Definition: htmlparse.c:85
int(* putstr)(void *chan, const char *str)
Definition: cgraph.h:184
Agraph_t * read(FILE *f)
Definition: gv.cpp:73