-/***************************************************************************\r
- * Copyright (C) 2009 By Duane Ellis *\r
- * openocd@duaneellis.com *\r
- * *\r
- * This program is free software; you can redistribute it and/or modify *\r
- * it under the terms of the GNU General Public License as published by *\r
- * the Free Software Foundation; either version 2 of the License, or *\r
- * (at your option) any later version. *\r
- * *\r
- * This program is distributed in the hope that it will be useful, *\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *\r
- * GNU General Public License for more details. *\r
- * *\r
- * You should have received a copy of the GNU General Public License *\r
- * along with this program; if not, write to the *\r
- * Free Software Foundation, Inc., *\r
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *\r
- ***************************************************************************/\r
-\r
-#include <stdio.h>\r
-#include <stdarg.h>\r
-#include <malloc.h>\r
-#include <string.h>\r
-\r
-#include "membuf.h"\r
-\r
-struct membuf {\r
- // buflen is alway "+1" bigger then\r
- // what is shown here, the +1 is for\r
- // the NULL string terminator\r
-#define DEFAULT_BUFSIZE 100 \r
- size_t maxlen; // allocated size\r
- size_t curlen; // where we are inserting at\r
- char *_strtoklast;\r
- void *buf;\r
-};\r
-\r
-\r
-#define space_avail( pBuf ) (pBuf->maxlen - pBuf->curlen)\r
-#define dataend( pBuf ) ( ((char *)(pBuf->buf)) + pBuf->curlen )\r
-\r
-size_t \r
-membuf_len( struct membuf *pBuf )\r
-{\r
- return pBuf->curlen;\r
-}\r
-\r
-const void *\r
-membuf_datapointer( struct membuf *pBuf )\r
-{\r
- return ((void *)(pBuf->buf));\r
-}\r
-\r
-const char *\r
-membuf_strtok( struct membuf *pBuf, const char *sep, void **pLast )\r
-{\r
- if( pBuf ){\r
- pBuf->_strtoklast = NULL;\r
- *pLast = pBuf;\r
- return strtok_r( ((char *)(pBuf->buf)), sep, &(pBuf->_strtoklast) );\r
- } else {\r
- // recover our pBuf\r
- pBuf = *((struct membuf **)(pLast));\r
- return strtok_r( NULL, sep, &(pBuf->_strtoklast) );\r
- }\r
-}\r
- \r
-\r
-\r
-struct membuf *\r
-membuf_new(void)\r
-{\r
- // by default - parameters are zero.\r
- struct membuf *pBuf;\r
-\r
- pBuf = calloc( 1, sizeof(*pBuf) );\r
- if( pBuf ){\r
- // we *ALWAYS* allocate +1 for null terminator.\r
- pBuf->buf = calloc( DEFAULT_BUFSIZE+1, sizeof(char));\r
- if( pBuf->buf == NULL ){\r
- free(pBuf);\r
- pBuf = NULL;\r
- } else {\r
- pBuf->maxlen = DEFAULT_BUFSIZE;\r
- }\r
- }\r
- return pBuf;\r
-}\r
-\r
-\r
-struct membuf *\r
-membuf_grow( struct membuf *pBuf, int n )\r
-{\r
- void *vp;\r
- signed int newsize;\r
-\r
- // this is a *SIGNED* value\r
- newsize = ((int)(pBuf->maxlen)) + n;\r
-\r
- // do not go negative, or too small\r
- if( newsize < DEFAULT_BUFSIZE ){\r
- newsize = DEFAULT_BUFSIZE;\r
- }\r
-\r
- // always alloc +1 for the null terminator\r
- vp = realloc( pBuf->buf, newsize+1 );\r
- if( vp ){\r
- pBuf->buf = vp;\r
- pBuf->maxlen = newsize;\r
- return pBuf;\r
- } else {\r
- return NULL;\r
- }\r
-}\r
-\r
-\r
-void membuf_reset( struct membuf *pBuf )\r
-{\r
- pBuf->curlen = 0;\r
-}\r
-\r
-\r
-void membuf_delete( struct membuf *pBuf )\r
-{\r
- if( pBuf ){\r
- if( pBuf->buf){\r
- // wack data so it cannot be reused\r
- memset(pBuf->buf,0,pBuf->maxlen);\r
- free(pBuf->buf);\r
- }\r
- // wack dat so it cannot be reused\r
- memset(pBuf,0,sizeof(pBuf));\r
- free(pBuf);\r
- }\r
-}\r
-\r
-int\r
-membuf_sprintf( struct membuf *pBuf , const char *fmt, ... )\r
-{\r
- int r;\r
- va_list ap;\r
- va_start( ap, fmt );\r
- r = membuf_vsprintf( pBuf, fmt, ap );\r
- va_end(ap);\r
- return r;\r
-}\r
-\r
-int\r
-membuf_vsprintf( struct membuf *pBuf, const char *fmt, va_list ap )\r
-{\r
- int r;\r
- size_t sa;\r
- int grew;\r
-\r
-\r
- grew = 0;\r
- for(;;) {\r
- sa = space_avail(pBuf);\r
-\r
- // do work\r
- r = vsnprintf( dataend( pBuf ),\r
- sa,\r
- fmt, \r
- ap );\r
- if( (r > 0) && (((size_t)(r)) < sa) ){\r
- // Success!\r
- pBuf->curlen += ((size_t)(r));\r
- // remember: We always alloc'ed +1\r
- // so this does not overflow\r
- ((char *)(pBuf->buf))[ pBuf->curlen ] = 0;\r
- r = 0;\r
- break;\r
- }\r
-\r
- // failure\r
- if( r < 0 ){\r
- // Option(A) format error\r
- // Option(B) glibc2.0 bug\r
- // assume (B).\r
- r = (4 * DEFAULT_BUFSIZE);\r
- }\r
-\r
- // don't do this again\r
- if( grew ){\r
- r = -1;\r
- break;\r
- }\r
- grew = 1;\r
- pBuf = membuf_grow( pBuf, r );\r
- if(pBuf == NULL){\r
- // grow failed\r
- r = -1;\r
- break;\r
- }\r
- }\r
- return r;\r
-}\r
-\r
-struct membuf *\r
-membuf_strcat( struct membuf *pBuf, const char *pStr )\r
-{\r
- return membuf_append( pBuf, pStr, strlen( pStr ) );\r
-}\r
-\r
-struct membuf *\r
-membuf_append( struct membuf *pBuf, const void *pData, size_t len )\r
-{\r
- size_t sa;\r
- int r;\r
-\r
- // how much room is there?\r
- sa = space_avail( pBuf );\r
-\r
- // will it fit?\r
- if( sa < len ){\r
- // if not, how much do we need?\r
- r = ((int)(sa - len));\r
- // do the grow.\r
- pBuf = membuf_grow( pBuf, r );\r
- // failed?\r
- if(pBuf==NULL){\r
- return pBuf;\r
- }\r
- }\r
- // append\r
- memcpy( dataend(pBuf),\r
- pData,\r
- len );\r
- pBuf->curlen += len;\r
- return pBuf;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
+/***************************************************************************
+ * Copyright (C) 2009 By Duane Ellis *
+ * openocd@duaneellis.com *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "membuf.h"
+
+struct membuf {
+ // buflen is alway "+1" bigger then
+ // what is shown here, the +1 is for
+ // the NULL string terminator
+#define DEFAULT_BUFSIZE 100
+ size_t maxlen; // allocated size
+ size_t curlen; // where we are inserting at
+ char *_strtoklast;
+ void *buf;
+};
+
+
+#define space_avail(pBuf) (pBuf->maxlen - pBuf->curlen)
+#define dataend(pBuf) (((char *)(pBuf->buf)) + pBuf->curlen)
+
+size_t
+membuf_len(struct membuf *pBuf)
+{
+ return pBuf->curlen;
+}
+
+const void *
+membuf_datapointer(struct membuf *pBuf)
+{
+ return ((void *)(pBuf->buf));
+}
+
+const char *
+membuf_strtok(struct membuf *pBuf, const char *sep, void **pLast)
+{
+ if (pBuf) {
+ pBuf->_strtoklast = NULL;
+ *pLast = pBuf;
+ // this should be "strtok_r()" but windows lacks */
+ return strtok(((char *)(pBuf->buf)), sep);
+ } else {
+ // recover our pBuf
+ pBuf = *((struct membuf **)(pLast));
+ // this should be "strtok_r()" but windows lacks */
+ return strtok( NULL, sep);
+ }
+}
+
+
+
+struct membuf *
+membuf_new(void)
+{
+ // by default - parameters are zero.
+ struct membuf *pBuf;
+
+ pBuf = calloc(1, sizeof(*pBuf));
+ if (pBuf) {
+ // we *ALWAYS* allocate +1 for null terminator.
+ pBuf->buf = calloc(DEFAULT_BUFSIZE + 1, sizeof(char));
+ if (pBuf->buf == NULL) {
+ free(pBuf);
+ pBuf = NULL;
+ } else {
+ pBuf->maxlen = DEFAULT_BUFSIZE;
+ }
+ }
+ return pBuf;
+}
+
+
+struct membuf *
+membuf_grow(struct membuf *pBuf, int n)
+{
+ void *vp;
+ signed int newsize;
+
+ // this is a *SIGNED* value
+ newsize = ((int)(pBuf->maxlen)) + n;
+
+ // do not go negative, or too small
+ if (newsize < DEFAULT_BUFSIZE) {
+ newsize = DEFAULT_BUFSIZE;
+ }
+
+ // always alloc +1 for the null terminator
+ vp = realloc(pBuf->buf, newsize + 1);
+ if (vp) {
+ pBuf->buf = vp;
+ pBuf->maxlen = newsize;
+ return pBuf;
+ } else {
+ return NULL;
+ }
+}
+
+
+void membuf_reset(struct membuf *pBuf)
+{
+ pBuf->curlen = 0;
+}
+
+
+void membuf_delete(struct membuf *pBuf)
+{
+ if (pBuf) {
+ if (pBuf->buf) {
+ // wack data so it cannot be reused
+ memset(pBuf->buf,0,pBuf->maxlen);
+ free(pBuf->buf);
+ }
+ // wack dat so it cannot be reused
+ memset(pBuf,0,sizeof(pBuf));
+ free(pBuf);
+ }
+}
+
+int
+membuf_sprintf(struct membuf *pBuf , const char *fmt, ...)
+{
+ int r;
+ va_list ap;
+ va_start(ap, fmt);
+ r = membuf_vsprintf(pBuf, fmt, ap);
+ va_end(ap);
+ return r;
+}
+
+int
+membuf_vsprintf(struct membuf *pBuf, const char *fmt, va_list ap)
+{
+ int r;
+ size_t sa;
+ int grew;
+
+
+ grew = 0;
+ for (;;) {
+ sa = space_avail(pBuf);
+
+ // do work
+ r = vsnprintf(dataend(pBuf),
+ sa,
+ fmt,
+ ap);
+ if ((r > 0) && (((size_t)(r)) < sa)) {
+ // Success!
+ pBuf->curlen += ((size_t)(r));
+ // remember: We always alloc'ed +1
+ // so this does not overflow
+ ((char *)(pBuf->buf))[ pBuf->curlen ] = 0;
+ r = 0;
+ break;
+ }
+
+ // failure
+ if (r < 0) {
+ // Option(A) format error
+ // Option(B) glibc2.0 bug
+ // assume (B).
+ r = (4 * DEFAULT_BUFSIZE);
+ }
+
+ // don't do this again
+ if (grew) {
+ r = -1;
+ break;
+ }
+ grew = 1;
+ pBuf = membuf_grow(pBuf, r);
+ if (pBuf == NULL) {
+ // grow failed
+ r = -1;
+ break;
+ }
+ }
+ return r;
+}
+
+struct membuf *
+membuf_strcat(struct membuf *pBuf, const char *pStr)
+{
+ return membuf_append(pBuf, pStr, strlen(pStr));
+}
+
+struct membuf *
+membuf_append(struct membuf *pBuf, const void *pData, size_t len)
+{
+ size_t sa;
+ int r;
+
+ // how much room is there?
+ sa = space_avail(pBuf);
+
+ // will it fit?
+ if (sa < len) {
+ // if not, how much do we need?
+ r = ((int)(sa - len));
+ // do the grow.
+ pBuf = membuf_grow(pBuf, r);
+ // failed?
+ if (pBuf == NULL) {
+ return pBuf;
+ }
+ }
+ // append
+ memcpy(dataend(pBuf),
+ pData,
+ len);
+ pBuf->curlen += len;
+ return pBuf;
+}
+
+
+
+
+
+