Code Search for Developers
 
 
  

misc_buf.c from EmStar at Krugle


Show misc_buf.c syntax highlighted

/*
 *
 * Copyright (c) 2003 The Regents of the University of California.  All 
 * rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Neither the name of the University nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
 

/*
 * implementation of 'buf_t' 
 *
 * $Id: misc_buf.c,v 1.41 2006/10/29 17:55:55 girod Exp $
 */

char misc_buf_c_cvsid[] = "$Id: misc_buf.c,v 1.41 2006/10/29 17:55:55 girod Exp $";

#include <stdarg.h>
#include <errno.h>

/*
 * Documentation on how to use a buf_t is found in include/misc_buf.h
 */


/**********************************************************************/

/*
 * this EASYBUILD craziness is to break a circular dependency between
 * libmisc and easybuild -- I want to use buf_t's as part of
 * easybuild, but easybuild is needed to compile libmisc
 */
#ifdef EASYBUILD
#include "libmisc/include/misc_buf.h"
#include "libmisc/include/comparisons.h"
#else
#include "misc.h"
#endif


/*
 * initialize an already allocated (e.g. stack-alloced) buf_t
 */
void buf_init(buf_t *b)
{
  memset(b, 0, sizeof(buf_t));
  bufcpy(b, "", 0);
}

/*
 * create a new buf_t
 */
buf_t *buf_new()
{
  buf_t *b = malloc(sizeof(buf_t));

  if (b == NULL) {
#ifndef EASYBUILD
	elog(LOG_CRIT, "Unable to alloc for buf!");
#endif
	exit(1);
  }
  
  if (b)
    buf_init(b);

  return b;
}


/*
 * destroy a buf_t
 */
void buf_free(buf_t *b)
{
  if (b) {
    if (b->buf)
      free(b->buf);
    free(b);
  }
}


/*
 * append additional information to a buf, possibly resizing it.
 *
 * NOTE: if src is NULL, it will just alloc space
 * NOTE: These functions leave a null-termination at the end of all
 * buffers, even for binary data.
 */
void bufcpy(buf_t *b, const void *src, int len)
{
  if (len < 0)
    return;

  if (!b)
    return;

  /* if there's enough room in the current buffer (including one space
     for terminating null), just copy into the existing buffer */
  if (b->len + len < b->alloc_size) {
    if (src) {
      memcpy(b->empty, src, len);
      buf_subsume(b, len);
    }
  } else {
    /* otherwise, make the buffer bigger by allocing a new one. */
    char *new_buf;
    int new_size = exponential_roundup(b->len + len + 1);

    if ((new_buf = realloc(b->buf, new_size)) == NULL) {
#ifndef EASYBUILD
      elog(LOG_CRIT, "out of memory");
#endif
      exit(1);
    }

    // printf("MALLOCING %d bytes\n", new_size);

    /* change over */
    b->buf = new_buf;
    b->alloc_size = new_size;
    b->empty = b->buf + b->len;

    if (src) {
      /* add the data from the buf the user just supplied */
      memcpy(new_buf + b->len, src, len);      
      buf_subsume(b, len);
    }
  }

  /* set the space after the last character to null */
  *(b->empty) = '\0';
}


void bufcpy_zeroes(buf_t *b, int len)
{
  bufcpy(b, NULL, len);
  memset(b->empty, 0, len);
  buf_subsume(b, len);
}


int buf_clear(buf_t *b, int dealloc)
{
  if (dealloc) {
    if (b->buf) free(b->buf);
    buf_init(b);
    return 0;
  }
  return buf_shorten(b, b->len);
}


void buf_swap(buf_t *a, buf_t *b)
{
  buf_t tmp;
  memmove(&tmp, a, sizeof(buf_t));
  memmove(a, b, sizeof(buf_t));
  memmove(b, &tmp, sizeof(buf_t));
} 


void steal_to_buf(buf_t *a, char *mem_to_steal, int size)
{
  if (a->buf) free(a->buf);
  a->buf = mem_to_steal;
  a->len = a->alloc_size = size;
  a->empty = a->buf + size;
}


int buf_shorten(buf_t *b, int count)
{
  if (count > b->len) {
#ifndef EASYBUILD
    elog(LOG_WARNING, "buf is %d bytes long, can't shorten by %d bytes",
	 b->len, count);
#endif
    return -1;
  }
  
  b->len -= count;
  b->empty -= count;

  return b->len;
}


int buf_remove(buf_t *buf, int start, int count)
{
  if (buf_shorten(buf, count) >= 0) {
    memmove(buf->buf + start,
	    buf->buf + start + count, buf->len - start);
    return buf->len;
  }
  return -1;
}


void bufprintf(buf_t *b, const char *fmt, ...)
{
  va_list ap;
  char tmp[32768];
  int len;

  /* print the string to a temp buffer.  too bad we don't have
   * asprintf generally available yet. */
  va_start(ap, fmt);
  len = vsnprintf(tmp, sizeof(tmp), fmt, ap);
  bufcpy(b, tmp, len);
  va_end(ap);
}


int bufcmp(buf_t *buf1, buf_t *buf2)
{
  int buf1_missing = (buf1 == NULL || buf1->len == 0);
  int buf2_missing = (buf2 == NULL || buf2->len == 0);
  int min_len;
  int result;

  /* both missing */
  if (buf1_missing && buf2_missing)
    return 0;
  
  /* one missing */
  if (buf1_missing) return -1;
  if (buf2_missing) return +1;

  /* both strings present, differ */
  min_len = i_min(buf1->len, buf2->len);
  result = memcmp(buf1->buf, buf2->buf, min_len);     
  if (result) return result;

  /* one is prefix of other */
  if (buf1->len > min_len) return +1;
  if (buf2->len > min_len) return -1;

  return 0;
}



void buf_print_raw(buf_t *buf, char *str, int len)
{
  int i;
  for (i=0; i<len; i++) {
    if (str[i] == '%') 
      bufprintf(buf, "%%25");
    else if (isprint(str[i])) 
      bufprintf(buf, "%c", str[i]);
    else
      bufprintf(buf, "%%%02X", (uint8_t)str[i]);
  }
}


char *buf_get(buf_t *buf)
{ return buf->buf; }

size_t buf_len(buf_t *buf)
{ return buf->len; }


void bufcat(buf_t *to, const buf_t *from)
{
  bufcpy(to, from->buf, from->len);
}


void buf_insert(buf_t *b, uint32_t offset, const void *src, uint32_t len)
{
  if (offset > b->len) {
#ifndef EASYBUILD
    elog(LOG_WARNING, "inserting past end of buf");
#endif
    return;
  }
  
  /* copy to maybe extend */
  bufcpy(b, src, len);
  if (src == NULL)
    buf_subsume(b, len);
  
  /* open space and copy */
  int move_length = b->len - offset - len;
  if (move_length > 0) {
    memmove(b->buf + offset + len, b->buf + offset, move_length);
    if (src)
      memmove(b->buf + offset, src, len);
    else
      memset(b->buf + offset, 0, len);
  }
}


int file_to_buf(buf_t *buf, const char *filename)
{
  int status;
  char rd_buf[4096];

  int fd = open(filename, O_RDONLY);
  if (fd < 0) return -1;

  while (1) {
    status = read(fd, rd_buf, sizeof(rd_buf));
    if (status < 0) {
      close(fd);
      return -1;
    }
    if (status == 0) {
      close(fd);
      return buf->len;
    }
    bufcpy(buf, rd_buf, status);
  }
}

int buf_to_file(const char *filename, buf_t *buf)
{
  int status = 0;
  int temp = 0;
  int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC,
		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
  if (fd <= 0) {
    return errno;
  }
  while (status < buf->len) {
    temp = write(fd, buf->buf + status, buf->len - status);
    if (temp < 0) {
      close(fd);
      return errno;
    }
    status += temp;
  }
  close(fd);
  return 0;
}

int buf_pop_chars(buf_t *buf, int count)
{
	if (count == 0) 
		return 0;
	if (buf->len < count)
		return -1;
	buf_shorten(buf, count);
	memmove(buf->buf, buf->buf+count, buf->len);
	return count;
}


/*
 *  pre-allocation support 
 */


void buf_prealloc(buf_t *buf, size_t space)
{
  if (buf_get_prealloc_len(buf) < space) {
    bufcpy(buf, NULL, space - buf_get_prealloc_len(buf));
  }
}


int buf_subsume(buf_t *b, size_t len)
{
  if (len <= buf_get_prealloc_len(b)) {
    b->len += len;
    b->empty += len;
    return 0;
  }
  return -1;
}

char *buf_get_prealloc_buf(buf_t *buf)
{
  return buf->buf + buf->len;
}

size_t buf_get_prealloc_len(buf_t *buf)
{
  return buf->alloc_size - buf->len - 1;
}


size_t buf_get_allocated_len(buf_t *buf)
{
  return buf->alloc_size;
}


/*
 *  buf_t item iterators
 *   the buf_t item iterator appends and traverses a buf_t composed of a 
 *   series of items, each of which is preceded by a length field.
 */


struct buf_iter {
  buf_t *buf;
  int cursor;
};


buf_iter_t *buf_item_iter_new(buf_t *buf)
{
  buf_iter_t *iter = (buf_iter_t*)malloc(sizeof(buf_iter_t));
  iter->buf = buf;
  iter->cursor = 0;
  return iter;
}


void buf_item_iter_set(buf_iter_t *to, buf_iter_t *from)
{
  memmove(to, from, sizeof(buf_iter_t));
}

void buf_item_iter_destroy(buf_iter_t *iter, int free_buf)
{
  if (iter) {
    if (free_buf && iter->buf) buf_free(iter->buf);
    free(iter);
  }
}


static
item_size_t buf_item_iter_length_aux(buf_iter_t *iter)
{
  item_size_t len;
  memmove(&len, iter->buf->buf + iter->cursor, sizeof(item_size_t));
  return len;
}


int buf_item_iter_valid(buf_iter_t *iter)
{
  if (iter && ((iter->buf->len - iter->cursor) >= sizeof(item_size_t))) {
    item_size_t len = buf_item_iter_length_aux(iter);
    if (len + iter->cursor + sizeof(item_size_t) > iter->buf->len) 
      return -1;
    return 1;
  }
  return 0;
}


item_size_t buf_item_iter_length(buf_iter_t *iter)
{
  if (buf_item_iter_valid(iter))
    return buf_item_iter_length_aux(iter);
  return 0;
}


int buf_item_iter_next(buf_iter_t *iter)
{
  if (buf_item_iter_valid(iter)) 
    iter->cursor += (sizeof(item_size_t) + buf_item_iter_length_aux(iter));
  return buf_item_iter_valid(iter);
}


void buf_item_iter_top(buf_iter_t *iter)
{
  iter->cursor = 0;
}


void buf_item_iter_remove(buf_iter_t *iter)
{
  if (buf_item_iter_valid(iter)) {
    buf_remove(iter->buf, iter->cursor, 
	       buf_item_iter_length_aux(iter) + sizeof(item_size_t));
  }
}


buf_t *buf_item_iter_get_buf(buf_iter_t *iter, buf_t *into)
{
  if (buf_item_iter_valid(iter)) {
    if (into == NULL)
      into = buf_new();
    bufcpy(into, iter->buf->buf + iter->cursor + sizeof(item_size_t), 
	   buf_item_iter_length_aux(iter));
    return into;
  }
  return NULL;
}


char *buf_item_iter_get_pointer(buf_iter_t *iter, int min_valid_length)
{
  if ((min_valid_length < 0) || 
      (buf_item_iter_length(iter) >= min_valid_length))
    return iter->buf->buf + iter->cursor + sizeof(item_size_t);
  return NULL;       
}

void buf_item_iter_append_str(buf_iter_t *iter, const char *str, int len)
{
  item_size_t length = len;
  bufcpy(iter->buf, (char*)&length, sizeof(length));
  bufcpy(iter->buf, str, len);
}


void buf_item_iter_append_buf(buf_iter_t *iter, buf_t *buf)
{
  buf_item_iter_append_str(iter, buf->buf, buf->len);
}






See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  elog.c
  elog_emit.c
  file.c
  misc_angles.c
  misc_buf.c
  misc_crc32.c
  misc_filename.c
  misc_hash.c
  misc_init.c
  misc_lock.c
  misc_math.c
  misc_namelist.c
  misc_network.c
  misc_nmea.c
  misc_opt.c
  misc_parse.c
  misc_proc.c
  misc_random.c
  misc_ringbuff.c
  misc_serial.c
  misc_signals.c
  misc_sim.c
  misc_time.c
  misc_types.c
  misc_version.c
  string.c