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

Manipulate Binary Text Bytes

Sections.
Interface
Implementation
Make.
Object.
switch $::tcl_platform(os) {
  Darwin - Linux - IRIX64 {
    compile -DNEED_MEMRCHR -c -o [
      export object
    ] [
      export implementation
    ] -- -list [import interface] [export interface]
  }
  default {
    error "do not how to build for $tcl_platform(os)"
  }
}
   
top

1 :: This is a command similar to "string" that operates on bytes rather than characters.

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.

   
   

Interface

   
top
2. bytes (1WY) ::

NAME

bytes — Byte operations.

synopsis

::wyrm::bytes append variable-name bytes...

::wyrm::bytes codes bytes from-index to-index

::wyrm::bytes codes bytes from-index -length length

::wyrm::bytes compare bytes bytes [ n ]

::wyrm::bytes concat bytes...

::wyrm::bytes diff bytes bytes [ start-index [ start-index ] ]

::wyrm::bytes equal bytes bytes [ n ]

::wyrm::bytes first bytes code [ start-index ]

::wyrm::bytes index bytes index

::wyrm::bytes last bytes code [ start-index ]

::wyrm::bytes length bytes

::wyrm::bytes printable bytes

::wyrm::bytes range bytes from-index to-index

::wyrm::bytes range bytes from-index -length length

::wyrm::bytes repeat bytes count

::wyrm::bytes replace bytes from-index to-index [ replacement ]

::wyrm::bytes replace bytes from-index -length length [ replacement ]

description

bytes is a small utility that does operations similar to string on 8 bit bytes rather 8 to 24 bit unicode characters.

bytes append v bytes1 bytes2 ... bytesn
Append each of the bytes to variable v. If v is not already defined, it is initialised to an empty string before adding bytes.
bytes codes bytes i j
Return a list of the codes of the bytes from index i through index j.
bytes compare bytes1 bytes2 [ n ]
Compare byte by byte until a difference; return whether the first is less, equal, or greater the second bytes. If n is specified, this is the maximum number of bytes to compare.
bytes concat bytes1 bytes2 ... bytesn
Return the concatenation each of the bytes.
bytes diff bytes1 bytes2 [ start1 [ start2 ] ]
Return the offset of the first different byte, or equivalently the length of longest common prefix. Comparison starts from the first bytes or the give start indices.
bytes equal bytes1 bytes2 [ n ]
1 if the bytes are equal, otherwise 0. If n is specified, this is the maximum number of bytes to compare.
bytes last bytes code [ start ]
code is the decimal byte value. Return the index of the first byte with this code. Return -1 if the byte is not found. If start is specified, the search starts from there rather than from the first byte.
bytes index bytes i
Return the code of the ith byte. The first byte is index 0.
bytes first bytes code [ start ]
code is the decimal byte value. Return the index of the last byte with this code. Return -1 if the byte is not found. If start is specified, the search starts after from there rather than from the last byte.
bytes length bytes
The number of bytes.
bytes printable bytes
bytes consists of alternately subsequences (each possibly empty) of printable (codes \x20 through \x7e) and nonprintable bytes with sequences lengths p1 n1 p2 n2 ... pl nl, pi printable bytes and then ni nonprintable bytes. The list of subsequence lengths is returned. If the bytes are empty, an empty list is returned.
bytes range bytes i j
Return the bytes from index i through index j.
bytes repeat bytes n
Return n repeated concatenated of the bytes.
bytes replace bytes i j [ replacement ]
Return the bytes with the bytes from index i through index j replaced. If replacement is omitted, the bytes are deleted.
 
section    top

#ifndef WYRM_BYTES_H
#define WYRM_BYTES_H

	//	wyrm-bytes - Copyright (C) 2002 SM Ryan.  All rights reserved.	
	
	#include "wyrmwif.h"
	
	int wyrm_bytesCommandInit(Intr intr);

#endif

		
   
   

Implementation

   
top

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

#include "wyrm-bytes.h"
#include "wyrm-io.h"

static int bytesCommand(ClientData clientData,Intr intr,int N,Tcl_Obj *const P[]);

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

static int position(Intr intr,Obj P,int m,int *offset) {
	chars OFFSET = Tcl_GetStringFromObj(P,0); int bias;
	if (strbegins("end",OFFSET)) {
		bias = m-1; OFFSET += 3;
	}else
		bias = 0;
	if (!*OFFSET)
		*offset = 0;
	else if (Tcl_GetInt(intr,OFFSET,offset)!=TCL_OK)
		return TCL_ERROR;
	*offset += bias;
	return TCL_OK;
}
static int range(Intr intr,int N,Tcl_Obj *const P[],int m,int *from,int *len) {
	if (position(intr,P[0],m,from)!=TCL_OK) return TCL_ERROR;
	if (N==2) {
		int to;
		if (position(intr,P[1],m,&to)!=TCL_OK) return TCL_ERROR;
		if (*from<0) *from = 0;
		*len = to - *from + 1;
	}else if (!strbegins("-l",Tcl_GetStringFromObj(P[1],0))) {
		return rprintf(intr,"%!this should be -length: %{y}s",TCL_ERROR,P[1]);
	}else {
		if (Tcl_GetIntFromObj(intr,P[2],len)!=TCL_OK) return TCL_ERROR;
		if (*from<0) {
			*len += *from; *from = 0;
		}
	}
	if (*len<=0) {
		*from = 0; *len = 0;
	}else {
		if (from<0) {
			*len -= *from; *from = 0;
		}
		if (*from+*len>m) {
			*len = m-*from;
		}
	}
	return TCL_OK;
}

static int byteslength(Obj obj) {
	int n; Tcl_GetByteArrayFromObj(obj,&n); return n;
}

#ifdef NEED_MEMRCHR
	static ptr memrchr(ptr s,int c,int n) {
		bytes S = s; unsigned C = 0xFF&c;
		while (n-->0) {
			if (S[n]==C) return S+n;
		}
		return 0;
	}
#endif

static int bytesCommand(ClientData clientData,Intr intr,int N,Tcl_Obj *const P[]) {
	Obj *P0 = P; int index;
	static chars subcommands[] = {
			"append","codes","compare","concatenate","difference",
			"equal","first","index","last","length",
			"printable","range","repeat","replace",
			0
	};
	if (N<=1) {
		Tcl_WrongNumArgs(intr,1,P0,"subcommand"); return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(intr,P[1],(CONST char**)subcommands,"subcommand",0,&index)!=TCL_OK) {
		return TCL_ERROR;
	}
	N -= 2; P += 2;
	switch (index) {
		case 0: {
			Obj var,val; int rc; bool copy,create; int i,totallength;
			bytes dd,ss; int ndd,nss;
			if (N<1) {
				Tcl_WrongNumArgs(intr,2,P0,"variable ..."); return TCL_ERROR;
			}
			var = *P++; N--;
			val = Tcl_ObjGetVar2(intr,var,0,0);
			if (N==0) {
				if (val) {
					return TCL_OK;
				}else {
					return Tcl_ObjSetVar2(intr,var,0,Tcl_NewObj(),TCL_LEAVE_ERR_MSG) ? TCL_OK : TCL_ERROR;
				}
			}
			copy = val && Tcl_IsShared(val);
			create = val==0;
			if (copy) {
				val = incr(Tcl_DuplicateObj(val));
			}else if (create) {
				val = incr(Tcl_NewObj());
			}				
			totallength = ndd = byteslength(val);
			for (i=0; i<N; i++) totallength += byteslength(P[i]);
			dd = Tcl_SetByteArrayLength(val,totallength);
			for (i=0; i<N; i++) {
				ss = Tcl_GetByteArrayFromObj(P[i],&nss);
				memcpy(dd+ndd,ss,nss); ndd += nss;
			}
			if (copy || create) {
				rc = Tcl_ObjSetVar2(intr,var,0,val,TCL_LEAVE_ERR_MSG) ? TCL_OK : TCL_ERROR;
				decr(val);
			}else
				rc = TCL_OK;
			return rc;
		}
		case 1: {
			int m; bytes a; int from,len,i; char D[20];
			if (N!=3 && N!=4) {
				Tcl_WrongNumArgs(intr,2,P0,"binary from [-length] to"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			if (range(intr,N-1,P+1,m,&from,&len)!=TCL_OK) return TCL_ERROR;
			Tcl_ResetResult(intr);
			for (i=from; i<from+len; i++) {
				sprintf(D,"%d",a[i]);
				Tcl_AppendElement(intr,D);
			}
			return TCL_OK;
		}
		case 2: {
			int m,n,l; bytes a,b; int cc;
			if (N!=2 && N!=3) {
				Tcl_WrongNumArgs(intr,2,P0,"binary binary [n]"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			b = Tcl_GetByteArrayFromObj(P[1],&n);
			if (N==3) {
				if (Tcl_GetIntFromObj(intr,P[2],&l)!=TCL_OK) return TCL_ERROR;
				if (m>l) m = l;
				if (n>l) n = l;
			}
			cc = m==n ? memcmp(a,b,m) : m-n;
			Tcl_SetObjResult(intr,Tcl_NewIntObj(cc));
			return TCL_OK;
		}
		case 3: {
			int n,m; bytes b;
			b = nheap(1,byte); m = 1; n = 0;
			while (N-->0) {
				int l; bytes a = Tcl_GetByteArrayFromObj(*P++,&l);
				if (l==0) continue;
				if (n+l>m) {
					m = 2*(n+l); b = reheap(m,byte,b);
				}
				memcpy(b+n,a,l); n+= l;
			}
			Tcl_SetObjResult(intr,Tcl_NewByteArrayObj(b,n));
			dispose(b);
			return TCL_OK;
		}
		case 4: {
			int m,n; bytes a,b; int i,starta=0,startb=0;
			if (2>N || N>4) {
				Tcl_WrongNumArgs(intr,2,P0,"binary [firststart [secondstart]]"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			b = Tcl_GetByteArrayFromObj(P[1],&n);
			if (N>=3) {
				if (Tcl_GetIntFromObj(intr,P[2],&starta)!=TCL_OK) return TCL_ERROR;
				if (N==4) {
					if (Tcl_GetIntFromObj(intr,P[3],&startb)!=TCL_OK) return TCL_ERROR;
				}
			}
			for (i=0; i<m-starta && i<n-startb; i++) {
				if (a[i+starta]!=b[i+startb]) break;
			}
			Tcl_SetObjResult(intr,Tcl_NewIntObj(i));
			return TCL_OK;
		}
		case 5: {
			int m,n,l; bytes a,b; int cc;
			if (N!=2 && N!=3) {
				Tcl_WrongNumArgs(intr,2,P0,"binary binary [n]"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			b = Tcl_GetByteArrayFromObj(P[1],&n);
			if (N==3) {
				if (Tcl_GetIntFromObj(intr,P[2],&l)!=TCL_OK) return TCL_ERROR;
				if (m>l) m = l;
				if (n>l) n = l;
			}
			cc = m==n ? memcmp(a,b,m) : m-n;
			Tcl_SetObjResult(intr,Tcl_NewIntObj(!cc));
			return TCL_OK;
		}
		case 6: {
			int m; bytes a,p; int code; int start;
			if (N!=2 && N!=3) {
				Tcl_WrongNumArgs(intr,2,P0,"binary bytecode [startindex]"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			if (Tcl_GetIntFromObj(intr,P[1],&code)!=TCL_OK) return TCL_ERROR;
			if (N==2) start = 0;
			else if (position(intr,P[2],m,&start)!=TCL_OK) return TCL_ERROR;
			p = memchr(a+start,code & 0xFF,m-start);
			Tcl_SetObjResult(intr,Tcl_NewIntObj(p ? p-a : -1));
			return TCL_OK;
		}
		case 7: {
			int m; bytes a; int offset;
			if (N!=2) {
				Tcl_WrongNumArgs(intr,2,P0,"binary offset"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			if (position(intr,P[1],m,&offset)!=TCL_OK) return TCL_ERROR;
			if (offset<0 || offset>=m) {
				Tcl_ResetResult(intr);
			}else {
				Tcl_SetObjResult(intr,Tcl_NewIntObj(a[offset]));
			}
			return TCL_OK;
		}
		case 8: {
			int m; bytes a,p; int code; int start;
			if (N!=2 && N!=3) {
				Tcl_WrongNumArgs(intr,2,P0,"binary bytecode [startindex]"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			if (Tcl_GetIntFromObj(intr,P[1],&code)!=TCL_OK) return TCL_ERROR;
			if (N==2) start = m-1;
			else if (position(intr,P[2],m,&start)!=TCL_OK) return TCL_ERROR;
			p = memrchr(a,code & 0xFF,start+1);
			Tcl_SetObjResult(intr,Tcl_NewIntObj(p ? p-a : -1));
			return TCL_OK;
		}
		case 9: {
			int m;
			if (N!=1) {
				Tcl_WrongNumArgs(intr,2,P0,"binary"); return TCL_ERROR;
			}
			Tcl_GetByteArrayFromObj(P[0],&m);
			Tcl_SetObjResult(intr,Tcl_NewIntObj(m));
			return TCL_OK;
		}
		case 10: {
			bytes a; int m,i=0,n; char D[50];
			if (N!=1) {
				Tcl_WrongNumArgs(intr,2,P0,"binary"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			Tcl_ResetResult(intr);
			while (i<m) {
				n = 0;
				while (i<m && ((32<=a[i] && a[i]<127) || a[i]=='\n')) {
					n++; i++;
				}
				sprintf(D,"%d",n); Tcl_AppendElement(intr,D);
				n = 0;
				while (i<m && !((32<=a[i] && a[i]<127) || a[i]=='\n')) {
					n++; i++;
				}
				sprintf(D,"%d",n); Tcl_AppendElement(intr,D);
			}
			return TCL_OK;
		}
		case 11: {
			int m; bytes a; int from,len;
			if (N!=3 && N!=4) {
				Tcl_WrongNumArgs(intr,2,P0,"binary from [-length] to"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			if (range(intr,N-1,P+1,m,&from,&len)!=TCL_OK) return TCL_ERROR;
			Tcl_SetObjResult(intr,Tcl_NewByteArrayObj(a+from,len));
			return TCL_OK;
		}
		case 12: {
			int m; bytes a; Obj result; bytes r; int n;
			if (N!=2) {
				Tcl_WrongNumArgs(intr,2,P0,"binary count"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			if (Tcl_GetIntFromObj(intr,P[1],&n)!=TCL_OK) return TCL_ERROR;
			result = incr(Tcl_NewObj());
			if (n*m>0) {
				r = Tcl_SetByteArrayLength(result,n*m);
				while (n-->0) {
					memcpy(r,a,m); r+=m;
				}
			}
			Tcl_SetObjResult(intr,result); decr(result);
			return TCL_OK;
		}
		case 13: {
			int m; bytes a; int n; bytes b; int from,len; Obj result; bytes r;
			if (3>N || N>5) {
				Tcl_WrongNumArgs(intr,2,P0,"binary from [-length] to [binary]"); return TCL_ERROR;
			}
			a = Tcl_GetByteArrayFromObj(P[0],&m);
			if (N==5 || N==4 && !strieq("-length",Tcl_GetStringFromObj(P[2],0))) {
				b = Tcl_GetByteArrayFromObj(P[N-1],&n); N--;
			}else {
				n = 0; b = 0;
			}
			if (range(intr,N-1,P+1,m,&from,&len)!=TCL_OK) return TCL_ERROR;
			result = incr(Tcl_NewObj());
			r = Tcl_SetByteArrayLength(result,m-len+n);
			memcpy(r,a,from);
			if (n) memcpy(r+from,b,n);
			memcpy(r+from+n,a+from+len,m-from-len);
			Tcl_SetObjResult(intr,result); decr(result);
			return TCL_OK;
		}
	}
}

		
 
section    top
    bytes utility.
      BYTE00
      append
        BYTEAA
        BYTEAB
        BYTEAC
        BYTEAD
        BYTEAE
      codes
        BYTEBA
        BYTEBB
        BYTEBC
        BYTEBD
        BYTEBE
        BYTEBF
        BYTEBG
        BYTEBH
        BYTEBI
        BYTEBJ
        BYTEBK
        BYTEBL
        BYTEBM
        BYTEBN
        BYTEBO
      concat
        BYTECA
        BYTECB
        BYTECC
        BYTECD
      equal
        BYTEDA
        BYTEDB
        BYTEDC
        BYTEDD
        BYTEDE
        BYTEDF
        BYTEDG
      first
        BYTEEA
        BYTEEB
        BYTEEC
        BYTEED
        BYTEEE
        BYTEEF
        BYTEEG
        BYTEEH
        BYTEEI
        BYTEEJ
        BYTEEK
      index
        BYTEFA
        BYTEFB
        BYTEFC
        BYTEFD
        BYTEFE
        BYTEFF
        BYTEFG
        BYTEFH
      length
        BYTEGA
        BYTEGB
        BYTEFC
        BYTEFD
      range
        BYTEHA
        BYTEHB
        BYTEHC
        BYTEHD
        BYTEHE
        BYTEHF
        BYTEHG
        BYTEHH
        BYTEHI
        BYTEHJ
        BYTEHK
        BYTEHL
        BYTEHM
        BYTEHN
        BYTEHO
      diff
        BYTEIA
        BYTEIB
        BYTEIC
        BYTEID
        BYTEIE
        BYTEIF
        BYTEIG
        BYTEIH
        BYTEII
        BYTEIJ
        BYTEIK
        BYTEIL
      printable
        BYTEJA
        BYTEJB
        BYTEJC
        BYTEJD
        BYTEJE
        BYTEJF
        BYTEJG
      compare
        BYTEKA
        BYTEKB
        BYTEKC
        BYTEKD
        BYTEKE
        BYTEKF
        BYTEKG
      last
        BYTELA
        BYTELB
        BYTELC
        BYTELD
        BYTELE
        BYTELF
        BYTELG
        BYTELH
        BYTELI
        BYTELJ
        BYTELK
      repeat
        BYTEMA
        BYTEMB
        BYTEMC
        BYTEMD
        BYTEME
      replace
        BYTENA
        BYTENB
        BYTENC
        BYTEND
        BYTENE
        BYTENF
        BYTENG