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
15 #include "tcldot.h"
16
17 /*
18 * myiodisc_afread - same api as read for libcgraph
19 *
20 * gets one line at a time from a Tcl_Channel and places it in a user buffer
21 * up to a maximum of n characters
22 *
23 * returns pointer to obtained line in user buffer, or
24 * returns NULL when last line read from memory buffer
25 *
26 * This is probably innefficient because it introduces
27 * one more stage of line buffering during reads (at least)
28 * but it is needed so that we can take full advantage
29 * of the Tcl_Channel mechanism.
30 */
myiodisc_afread(void * channel,char * ubuf,int n)31 int myiodisc_afread(void* channel, char *ubuf, int n)
32 {
33 static Tcl_DString dstr;
34 static int strpos;
35 int nput;
36
37 if (!n) { /* a call with n==0 (from aglexinit) resets */
38 *ubuf = '\0';
39 strpos = 0;
40 return 0;
41 }
42
43 /*
44 * the user buffer might not be big enough to hold the line.
45 */
46 if (strpos) {
47 nput = Tcl_DStringLength(&dstr) - strpos;
48 if (nput > n) {
49 /* chunk between first and last */
50 memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), n);
51 strpos += n;
52 nput = n;
53 ubuf[n] = '\0';
54 } else {
55 /* last chunk */
56 memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), nput);
57 strpos = 0;
58 }
59 } else {
60 Tcl_DStringFree(&dstr);
61 Tcl_DStringInit(&dstr);
62 if (Tcl_Gets((Tcl_Channel) channel, &dstr) < 0) {
63 /* probably EOF, but could be other read errors */
64 *ubuf = '\0';
65 return 0;
66 }
67 /* linend char(s) were stripped off by Tcl_Gets,
68 * append a canonical linenend. */
69 Tcl_DStringAppend(&dstr, "\n", 1);
70 if (Tcl_DStringLength(&dstr) > n) {
71 /* first chunk */
72 nput = n;
73 memcpy(ubuf, Tcl_DStringValue(&dstr), n);
74 strpos = n;
75 } else {
76 /* single chunk */
77 nput = Tcl_DStringLength(&dstr);
78 memcpy(ubuf, Tcl_DStringValue(&dstr),nput);
79 }
80 }
81 return nput;
82 }
83
84
85 /* exact copy from cgraph/io.c - but that one is static */
myiodisc_memiofread(void * chan,char * buf,int bufsize)86 int myiodisc_memiofread(void *chan, char *buf, int bufsize)
87 {
88 const char *ptr;
89 char *optr;
90 char c;
91 int l;
92 rdr_t *s;
93
94 if (bufsize == 0) return 0;
95 s = (rdr_t *) chan;
96 if (s->cur >= s->len)
97 return 0;
98 l = 0;
99 ptr = s->data + s->cur;
100 optr = buf;
101 do {
102 *optr++ = c = *ptr++;
103 l++;
104 } while (c && (c != '\n') && (l < bufsize));
105 s->cur += l;
106 return l;
107 }
108
109 #if 0
110 Agraph_t *agread_usergets (ictx_t *ictx, FILE * fp, int (*usergets)(void *chan, char *buf, int bufsize))
111 {
112 Agraph_t* g;
113 Agiodisc_t ioDisc;
114
115 ioDisc.afread = usergets;
116 ioDisc.putstr = AgIoDisc.putstr;
117 ioDisc.flush = AgIoDisc.flush;
118
119 ictx->mydisc.io = &ioDisc;
120 g = agread (fp, (Agdisc_t *)ictx);
121 ictx->mydisc.io = &AgIoDisc; /* restore io */
122 return g;
123 }
124
125 #endif
126