DNA.
wyrm-data
Version.
1.0.9
Namespace.
::wyrm
Command.
::wyrm::data
Language.
c
Manpage.
data (1WY)
Manpage.
wyrm_dataRead (3WY)
Manpage.
wyrm_dataWrite (3WY)
Testbase.
Test Script
Test Report
Import.
Interface.
wyrmwif
Export.
Implementation.
wyrm-data.c
Interface.
wyrm-data.h
Object.
wyrm-data.o

Memory Bufferred I/O Channels

Sections.
Memory bufferred channels
Read Only Channel
Write Only Channel
Make.
Object.
compile -c -o [
  export object
] [
  export implementation
] -- -list [import interface] [export interface]
   
top

1 :: A read-only channel which dribbles out a string. A write-only channel that accumulates a string until closed.

Copyright (C) 2002 SM Ryan

Wyrmwif Tcl extensions. For non-profit uses only, provided this copyright is preserved on all copies, this work may be freely copied, modified, redistributed, compiled, and incorporated in other works. This work is distributed with no warranty of any kind; no author or distributor accepts any responsibility for the consequences of using it, or for whether it serves any particular purpose or works at all, unless he or she says so in writing.

   
   

Memory bufferred channels

   
top
 
section    top
		
#ifndef WYRM_DATA_H
#define WYRM_DATA_H

	//	wyrm-data.dna - Copyright (C) 2002 SM Ryan.  All rights reserved.

	#include "wyrmwif.h"

	<extern declarations>

#endif

		
 
section    top

static int dataCommand(ClientData clientData,Intr intr,int N,Tcl_Obj *const P[]) {
	chars p = N>=2 ? Tcl_GetStringFromObj(P[1],0) : ""; Tcl_Channel ch;
	Tcl_ResetResult(intr);
	if (stribegins("a",p) ? N!=4 : N!=3) {
		usage:
			Tcl_AppendResult(intr,
					"usage: data read <data> | data write <closescript> | data argument <channel> <argument>",
					0);
			return TCL_ERROR;
	}
	if (stribegins("r",p))
		ch = wyrm_dataRead(P[2]);
	else if (stribegins("w",p))
		ch = wyrm_dataWrite(P[2]);
	else if (stribegins("a",p))
		return wyrm_dataWriteArgument(intr,Tcl_GetString(P[2]),P[3]);
	else {
		Tcl_AppendResult(intr,"expected 'read' or 'write' or 'argument': ",p,"\n",0); goto usage;
	}
	Tcl_RegisterChannel(intr,ch);
	Tcl_SetResult(intr,Tcl_GetChannelName(ch),TCL_VOLATILE);
	return TCL_OK;
}

int wyrm_dataCommandInit(Intr intr) {
	char package[] = "namespace eval ::wyrm {namespace export data}\n";
	Tcl_CreateObjCommand(intr,"::wyrm::data",dataCommand,0,0);
	return Tcl_Eval(intr,package);
}

		
    data command.
      Reading.
        DAT500
      Writing.
        DAT501
      Parameters.
        Too few.
          DAT502
        Too many.
          DAT503
        Invalid.
          DAT504
 
section    top
int wyrm_dataCommandInit(Intr intr);
		
   
   

Read Only Channel

   
top
 
section    top
 
section    top

typedef struct {
	Obj		buffer;
	int		off;
} ReadDataContext,*pReadDataContext;

static void dataWatcher(ptr c,int mask) {
	return;
}
static int dataHandle(ptr c,int direction,ptr *handle) {
	return TCL_ERROR;
}

static int readDataClose(ptr c,Intr intr) {
	pReadDataContext C = c; decr(C->buffer); dispose(C);
	return TCL_OK;
}

static int readDataRead(ptr c,chars buf,int size,int *err) {
	pReadDataContext	C = c;
	int n; chars		s = Tcl_GetStringFromObj(C->buffer,&n);
	n -= C->off; s += C->off;
	if (n>size) n = size;
	memcpy(buf,s+C->off,n);
	C->off += n;
	return n;
}

static int readDataWriteInvalid(ptr c,chars buf,int size,int *err) {
	*err = 22; return -1;
}

static Tcl_ChannelType readDataChannel = {
	"WyrmReadData",
	TCL_CHANNEL_VERSION_2,
	readDataClose,
	readDataRead,
	(Tcl_DriverOutputProc*)readDataWriteInvalid,
	0,
	0,
	0,
	dataWatcher,
	dataHandle,
	0,
	0,
	0,
	0,
	0,
};

Tcl_Channel wyrm_dataRead(Obj text) {
	pReadDataContext C = heap(ReadDataContext); char name[40];
	TCL_DECLARE_MUTEX(Klock);
	static int K; int k;
	Tcl_MutexLock(Klock);
	k = ++K;
	Tcl_MutexUnlock(Klock);
	C->buffer = incr(text); C->off = 0;
	sprintf(name,"wyrmReadData%d",k);
	return Tcl_CreateChannel(&readDataChannel,name,C,TCL_READABLE);
}

		
    Read channel.
      Reading
        DAT100
        DAT101
        DAT102
      Writing.
        DAT110
 
section    top
Tcl_Channel wyrm_dataRead(Obj text);
		
   
   

Write Only Channel

   
top
 
section    top
 
section    top

typedef struct {
	Obj	buffer;
	Obj	closeScript;
} WriteDataContext,*pWriteDataContext;

static int writeDataClose(ptr c,Intr intr) {
	pWriteDataContext	C = c;
	Obj					script = C->closeScript;
	int					rc;
	if (!intr) return 0;
	if (Tcl_IsShared(script)) {
		decr(script); script = incr(Tcl_DuplicateObj(C->closeScript));
	}
	rc = Tcl_ListObjAppendElement(intr,script,C->buffer);
	if (rc==TCL_OK) rc = Tcl_GlobalEvalObj(intr,script);
	else Tcl_AppendResult(intr,"\nwhile appending the closed buffer to data script.");
	decr(script); decr(C->buffer); dispose(C);
	return rc==TCL_OK ? 0 : 5;
}

static int writeDataReadInvalid(ptr c,chars buf,int size,int *err) {
	*err = 22; return -1;
}

static int writeDataWrite(ptr c,chars buf,int size,int *err) {
	pWriteDataContext	C = c;
	if (size>=0) Tcl_AppendToObj(C->buffer,buf,size);
	return size;
}

static Tcl_ChannelType writeDataChannel = {
	"WyrmWriteData",
	TCL_CHANNEL_VERSION_2,
	writeDataClose,
	writeDataReadInvalid,
	(Tcl_DriverOutputProc*)writeDataWrite,
	0,
	0,
	0,
	dataWatcher,
	dataHandle,
	0,
	0,
	0,
	0,
	0,
};

Tcl_Channel wyrm_dataWrite(Obj closeScript) {
	pWriteDataContext C = heap(WriteDataContext); char name[40];
	TCL_DECLARE_MUTEX(Klock);
	static int K; int k;
	Tcl_MutexLock(Klock);
	k = ++K;
	Tcl_MutexUnlock(Klock);
	C->buffer = incr(Tcl_NewObj()); C->closeScript = incr(closeScript);
	sprintf(name,"wyrmWriteData%d",k);
	return Tcl_CreateChannel(&writeDataChannel,name,C,TCL_WRITABLE);
}

		
 
section    top
Tcl_Channel wyrm_dataWrite(Obj closeScript);
		
 
section    top

int wyrm_dataWriteArgument(Intr intr,chars channelName,Obj argument) {
	int mode; Tcl_Channel channel = Tcl_GetChannel(intr, channelName,&mode);
	pWriteDataContext C = channel ? Tcl_GetChannelInstanceData(channel) : 0;
	if (channel && strbegins("wyrmWriteData",channelName) && (mode&TCL_WRITABLE)) {
		if (Tcl_IsShared(C->closeScript)) {
			Obj t = incr(Tcl_DuplicateObj(C->closeScript));
			decr(C->closeScript); C->closeScript = t;
		}
		return Tcl_ListObjAppendElement(intr,C->closeScript,argument);
	}else
		return rprintf(intr,"%!not a data-write channel",TCL_ERROR);
}

		
    Append an argument
      DAT170
      DAT171
      DAT172
      DAT173
 
section    top
int wyrm_dataWriteArgument(Intr intr,chars channelName,Obj argument);
		
 
section    top

static const char COPYRIGHT[] = "wyrm-data.dna - Copyright (C) 2002 SM Ryan.  All rights reserved.";

#include "wyrm-data.h"

<Data command>
<Data read>
<Data write>
<Data write argument>

		
 
section    top