1/* -*- Mode: c++ -*-
2 * $Id: xotclUtil.c,v 1.3 2006/02/18 22:17:33 neumann Exp $
3 *
4 *  Extended Object Tcl (XOTcl)
5 *
6 *  Copyright (C) 1999-2008 Gustaf Neumann, Uwe Zdun
7 *
8 *
9 *  xotclUtil.c --
10 *
11 *  Utility functions
12 *
13 */
14
15#include "xotclInt.h"
16
17char *
18XOTcl_ltoa(char *buf, long i, int *len)  /* fast version of sprintf(buf,"%ld",l); */ {
19  int nr_written, negative;
20  char tmp[LONG_AS_STRING], *pointer = &tmp[1], *string, *p;
21  *tmp = 0;
22
23  if (i<0) {
24    i = -i;
25    negative = nr_written = 1;
26  } else
27    nr_written = negative = 0;
28
29  do {
30    nr_written++;
31    *pointer++ = i%10 + '0';
32    i/=10;
33  } while (i);
34
35  p = string = buf;
36  if (negative)
37    *p++ = '-';
38
39  while ((*p++ = *--pointer));   /* copy number (reversed) from tmp to buf */
40  if (len) *len = nr_written;
41  return string;
42}
43
44
45static char *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
46static int blockIncrement = 8;
47/*
48static char *alphabet = "ab";
49static int blockIncrement = 2;
50*/
51static unsigned char chartable[255] = {0};
52
53
54char *
55XOTclStringIncr(XOTclStringIncrStruct *iss) {
56  char newch, *currentChar;
57
58  currentChar = iss->buffer + iss->bufSize - 2;
59  newch = *(alphabet + chartable[(unsigned)*currentChar]);
60
61  while (1) {
62    if (newch) { /* no overflow */
63      *currentChar = newch;
64      break;
65    } else {     /* overflow */
66      *currentChar = *alphabet; /* use first char from alphabet */
67      currentChar--;
68      assert(currentChar >= iss->buffer);
69
70      newch = *(alphabet + chartable[(unsigned)*currentChar]);
71      if (currentChar < iss->start) {
72	iss->length++;
73	if (currentChar == iss->buffer) {
74	  size_t newBufSize = iss->bufSize + blockIncrement;
75	  char *newBuffer = ckalloc(newBufSize);
76	  currentChar = newBuffer+blockIncrement;
77	  /*memset(newBuffer, 0, blockIncrement);*/
78	  memcpy(currentChar, iss->buffer, iss->bufSize);
79	  *currentChar = newch;
80	  iss->start = currentChar;
81	  ckfree(iss->buffer);
82	  iss->buffer = newBuffer;
83	  iss->bufSize = newBufSize;
84	} else {
85	  iss->start = currentChar;
86	}
87      }
88    }
89  }
90  assert(iss->buffer[iss->bufSize-1] == 0);
91  assert(iss->buffer[iss->bufSize-2] != 0);
92  assert(iss->length < iss->bufSize);
93  assert(iss->start + iss->length + 1 == iss->buffer + iss->bufSize);
94
95  return iss->start;
96}
97
98
99void
100XOTclStringIncrInit(XOTclStringIncrStruct *iss) {
101  char *p;
102  int i = 0;
103  const size_t bufSize = blockIncrement>2 ? blockIncrement : 2;
104
105  for (p=alphabet; *p; p++) {
106    chartable[(int)*p] = ++i;
107  }
108
109  iss->buffer = ckalloc(bufSize);
110  memset(iss->buffer, 0, bufSize);
111  iss->start    = iss->buffer + bufSize-2;
112  iss->bufSize  = bufSize;
113  iss->length   = 1;
114  /*
115    for (i=1; i<50; i++) {
116      XOTclStringIncr(iss);
117      fprintf(stderr, "string '%s' (%d)\n",  iss->start, iss->length);
118    }
119  */
120}
121
122void
123XOTclStringIncrFree(XOTclStringIncrStruct *iss) {
124  ckfree(iss->buffer);
125}
126