File: tcldot-io.c

package info (click to toggle)
graphviz 14.0.5-2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 139,388 kB
  • sloc: ansic: 141,938; cpp: 11,957; python: 7,766; makefile: 4,043; yacc: 3,030; xml: 2,972; tcl: 2,495; sh: 1,388; objc: 1,159; java: 560; lex: 423; perl: 243; awk: 156; pascal: 139; php: 58; ruby: 49; cs: 31; sed: 1
file content (109 lines) | stat: -rw-r--r-- 2,961 bytes parent folder | download | duplicates (2)
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
/*************************************************************************
 * Copyright (c) 2011 AT&T Intellectual Property 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors: Details at https://graphviz.org
 *************************************************************************/

#include "../tcl-compat.h"
#include <assert.h>
#include <cgraph/rdr.h>
#include <limits.h>
#include <stddef.h>
#include "tcldot.h"

/*
 * myiodisc_afread - same api as read for libcgraph
 *
 * gets one line at a time from a Tcl_Channel and places it in a user buffer
 *    up to a maximum of n characters
 *
 * returns pointer to obtained line in user buffer, or
 * returns NULL when last line read from memory buffer
 *
 * This is probably innefficient because it introduces
 * one more stage of line buffering during reads (at least)
 * but it is needed so that we can take full advantage
 * of the Tcl_Channel mechanism.
 */
int myiodisc_afread(void* channel, char *ubuf, int n)
{
    assert(n >= 0);

    static Tcl_DString dstr;
    static Tcl_Size strpos;
    Tcl_Size nput;

    if (!n) {			/* a call with n==0 (from aglexinit) resets */
	*ubuf = '\0';
	strpos = 0;
	return 0;
    }

    /* 
     * the user buffer might not be big enough to hold the line.
     */
    if (strpos) {
	nput = Tcl_DStringLength(&dstr) - strpos;
	if (nput > n) {
	    /* chunk between first and last */
	    memcpy(ubuf, strpos + Tcl_DStringValue(&dstr), (size_t)n);
	    strpos += n;
	    nput = n;
	    ubuf[n] = '\0';
	} else {
	    /* last chunk */
	    memcpy(ubuf, strpos + Tcl_DStringValue(&dstr), (size_t)nput);
	    strpos = 0;
	}
    } else {
	Tcl_DStringFree(&dstr);
	Tcl_DStringInit(&dstr);
	if (Tcl_Gets((Tcl_Channel) channel, &dstr) < 0) {
	    /* probably EOF, but could be other read errors */
	    *ubuf = '\0';
	    return 0;
	}
	/* linend char(s) were stripped off by Tcl_Gets,
	 * append a canonical linenend. */
	Tcl_DStringAppend(&dstr, "\n", 1);
	if (Tcl_DStringLength(&dstr) > n) {
	    /* first chunk */
	    nput = n;
	    memcpy(ubuf, Tcl_DStringValue(&dstr), (size_t)n);
	    strpos = n;
	} else {
	    /* single chunk */
	    nput = Tcl_DStringLength(&dstr);
	    memcpy(ubuf, Tcl_DStringValue(&dstr), (size_t)nput);
	}
    }
    return (int)nput;
}


/* exact copy from cgraph/io.c - but that one is static */
int myiodisc_memiofread(void *chan, char *buf, int bufsize)
{
    const char *ptr;
    char *optr;
    char c;
    rdr_t *s;

    if (bufsize == 0) return 0;
    s = chan;
    if (s->cur >= s->len)
        return 0;
    size_t l = 0;
    ptr = s->data + s->cur;
    optr = buf;
    do {
        *optr++ = c = *ptr++;
        l++;
    } while (c && c != '\n' && l < INT_MAX && (int)l < bufsize);
    s->cur += l;
    return (int)l;
}