C language description

16.  bit

bits.c

/*
 * Copyright (C) 2018 Swift Navigation Inc.
 * Contact: Swift Navigation <dev@swiftnav.com>
 *
 * This source is subject to the license found in the file 'LICENSE' which must
 * be distributed together with this source. All other rights reserved.
 *
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <rtcm3/bits.h>

/** Get bit field from buffer as an unsigned integer.
 * Unpacks `len` bits at bit position `pos` from the start of the buffer.
 * Maximum bit field length is 32 bits, i.e. `len <= 32`.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * 
eturn Bit field as an unsigned value.
 */
uint32_t rtcm_getbitu(const uint8_t *buff, uint32_t pos, uint8_t len) {
  uint32_t bits = 0;

  for (uint32_t i = pos; i < pos + len; i++) {
    bits = (bits << 1) + ((buff[i / 8] >> (7 - i % 8)) & 1u);
  }

  return bits;
}

/** Get bit field from buffer as an unsigned long integer.
 * Unpacks `len` bits at bit position `pos` from the start of the buffer.
 * Maximum bit field length is 64 bits, i.e. `len <= 64`.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * 
eturn Bit field as an unsigned value.
 */
uint64_t rtcm_getbitul(const uint8_t *buff, uint32_t pos, uint8_t len) {
  uint64_t bits = 0;

  for (uint32_t i = pos; i < pos + len; i++) {
    bits = (bits << 1) + ((buff[i / 8] >> (7 - i % 8)) & 1u);
  }

  return bits;
}

/** Get bit field from buffer as a signed integer.
 * Unpacks `len` bits at bit position `pos` from the start of the buffer.
 * Maximum bit field length is 32 bits, i.e. `len <= 32`.
 *
 * This function sign extends the `len` bit field to a signed 32 bit integer.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * 
eturn Bit field as a signed value.
 */
int32_t rtcm_getbits(const uint8_t *buff, uint32_t pos, uint8_t len) {
  int32_t bits = (int32_t)rtcm_getbitu(buff, pos, len);

  /* Sign extend, taken from:
   * http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
   */
  int32_t m = 1u << (len - 1);
  return (bits ^ m) - m;
}

/** Get bit field from buffer as a signed integer.
 * Unpacks `len` bits at bit position `pos` from the start of the buffer.
 * Maximum bit field length is 64 bits, i.e. `len <= 64`.
 *
 * This function sign extends the `len` bit field to a signed 64 bit integer.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * 
eturn Bit field as a signed value.
 */
int64_t rtcm_getbitsl(const uint8_t *buff, uint32_t pos, uint8_t len) {
  int64_t bits = (int64_t)rtcm_getbitul(buff, pos, len);

  /* Sign extend, taken from:
   * http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
   */
  int64_t m = ((uint64_t)1) << (len - 1);
  return (bits ^ m) - m;
}

/** Set bit field in buffer from an unsigned integer.
 * Packs `len` bits into bit position `pos` from the start of the buffer.
 * Maximum bit field length is 32 bits, i.e. `len <= 32`.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * param data Unsigned integer to be packed into bit field.
 */
void rtcm_setbitu(uint8_t *buff, uint32_t pos, uint32_t len, uint32_t data) {
  uint32_t mask = 1u << (len - 1);

  if (len <= 0 || 32 < len) {
    return;
  }

  for (uint32_t i = pos; i < pos + len; i++, mask >>= 1) {
    if (data & mask) {
      buff[i / 8] |= 1u << (7 - i % 8);
    } else {
      buff[i / 8] &= ~(1u << (7 - i % 8));
    }
  }
}

/** Set bit field in buffer from an unsigned integer.
 * Packs `len` bits into bit position `pos` from the start of the buffer.
 * Maximum bit field length is 64 bits, i.e. `len <= 64`.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * param data Unsigned integer to be packed into bit field.
 */
void rtcm_setbitul(uint8_t *buff, uint32_t pos, uint32_t len, uint64_t data) {
  uint64_t mask = ((uint64_t)1) << (len - 1);

  if (len <= 0 || 64 < len) {
    return;
  }

  for (uint32_t i = pos; i < pos + len; i++, mask >>= 1) {
    if (data & mask) {
      buff[i / 8] |= ((uint64_t)1) << (7 - i % 8);
    } else {
      buff[i / 8] &= ~(((uint64_t)1) << (7 - i % 8));
    }
  }
}

/** Set bit field in buffer from a signed integer.
 * Packs `len` bits into bit position `pos` from the start of the buffer.
 * Maximum bit field length is 32 bits, i.e. `len <= 32`.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * param data Signed integer to be packed into bit field.
 */
void rtcm_setbits(uint8_t *buff, uint32_t pos, uint32_t len, int32_t data) {
  rtcm_setbitu(buff, pos, len, (uint32_t)data);
}

/** Set bit field in buffer from a signed integer.
 * Packs `len` bits into bit position `pos` from the start of the buffer.
 * Maximum bit field length is 32 bits, i.e. `len <= 32`.
 *
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * param data Signed integer to be packed into bit field.
 */
void rtcm_setbitsl(uint8_t *buff, uint32_t pos, uint32_t len, int64_t data) {
  rtcm_setbitul(buff, pos, len, (uint64_t)data);
}

/* Get sign-magnitude bits, See Note 1, Table 3.3-1, RTCM 3.3
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * 
eturn Bit field as a signed value.
 */
int32_t rtcm_get_sign_magnitude_bit(const uint8_t *buff,
                                    uint32_t pos,
                                    uint8_t len) {
  int32_t value = rtcm_getbitu(buff, pos + 1, len - 1);
  return rtcm_getbitu(buff, pos, 1) ? -value : value;
}

/* Set sign-magnitude bits, See Note 1, Table 3.3-1, RTCM 3.3
 * param buff
 * param pos Position in buffer of start of bit field in bits.
 * param len Length of bit field in bits.
 * data data to encode
 */
void rtcm_set_sign_magnitude_bit(uint8_t *buff,
                                 uint32_t pos,
                                 uint8_t len,
                                 int64_t data) {
  rtcm_setbitu(buff, pos, 1, (data < 0) ? 1 : 0);
  rtcm_setbitu(buff, pos + 1, len - 1, ((data < 0) ? -data : data));
}

bits.h

/*
 * Copyright (C) 2018 Swift Navigation Inc.
 * Contact: Swift Navigation <dev@swiftnav.com>
 *
 * This source is subject to the license found in the file 'LICENSE' which must
 * be distributed together with this source. All other rights reserved.
 *
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef SWIFTNAV_RTCM3_BITS_H
#define SWIFTNAV_RTCM3_BITS_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

uint32_t rtcm_getbitu(const uint8_t *buff, uint32_t pos, uint8_t len);
uint64_t rtcm_getbitul(const uint8_t *buff, uint32_t pos, uint8_t len);
int32_t rtcm_getbits(const uint8_t *buff, uint32_t pos, uint8_t len);
int64_t rtcm_getbitsl(const uint8_t *buff, uint32_t pos, uint8_t len);
void rtcm_setbitu(uint8_t *buff, uint32_t pos, uint32_t len, uint32_t data);
void rtcm_setbitul(uint8_t *buff, uint32_t pos, uint32_t len, uint64_t data);
void rtcm_setbits(uint8_t *buff, uint32_t pos, uint32_t len, int32_t data);
void rtcm_setbitsl(uint8_t *buff, uint32_t pos, uint32_t len, int64_t data);
int32_t rtcm_get_sign_magnitude_bit(const uint8_t *buff,
                                    uint32_t pos,
                                    uint8_t len);
void rtcm_set_sign_magnitude_bit(uint8_t *buff,
                                    uint32_t pos,
                                    uint8_t len,
                                    int64_t data);
#ifdef __cplusplus
}
#endif

#endif /* SWIFTNAV_RTCM3_BITS_H */

 

15. list

redis-4.0.11srcadlist.h

/* adlist.h - A generic doubly linked list implementation
 *
 * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
 * 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.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Redis 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
 */

#ifndef __ADLIST_H__
#define __ADLIST_H__

/* Node, List, and Iterator are the only data structures used currently. */

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);
    void (*free)(void *ptr);
    int (*match)(void *ptr, void *key);
    unsigned long len;
} list;

/* Functions implemented as macros */
#define listLength(l) ((l)->len)
#define listFirst(l) ((l)->head)
#define listLast(l) ((l)->tail)
#define listPrevNode(n) ((n)->prev)
#define listNextNode(n) ((n)->next)
#define listNodeValue(n) ((n)->value)

#define listSetDupMethod(l,m) ((l)->dup = (m))
#define listSetFreeMethod(l,m) ((l)->free = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))

#define listGetDupMethod(l) ((l)->dup)
#define listGetFree(l) ((l)->free)
#define listGetMatchMethod(l) ((l)->match)

/* Prototypes */
list *listCreate(void);
void listRelease(list *list);
void listEmpty(list *list);
list *listAddNodeHead(list *list, void *value);
list *listAddNodeTail(list *list, void *value);
list *listInsertNode(list *list, listNode *old_node, void *value, int after);
void listDelNode(list *list, listNode *node);
listIter *listGetIterator(list *list, int direction);
listNode *listNext(listIter *iter);
void listReleaseIterator(listIter *iter);
list *listDup(list *orig);
listNode *listSearchKey(list *list, void *key);
listNode *listIndex(list *list, long index);
void listRewind(list *list, listIter *li);
void listRewindTail(list *list, listIter *li);
void listRotate(list *list);
void listJoin(list *l, list *o);

/* Directions for iterators */
#define AL_START_HEAD 0
#define AL_START_TAIL 1

#endif /* __ADLIST_H__ */

redis-4.0.11srcadlist.c

/* adlist.c - A generic doubly linked list implementation
 *
 * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
 * 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.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Redis 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
 */


#include <stdlib.h>
#include "adlist.h"

/* Create a new list. The created list can be freed with
 * AlFreeList(), but private value of every node need to be freed
 * by the user before to call AlFreeList().
 *
 * On error, NULL is returned. Otherwise the pointer to the new list. */
list *listCreate(void)
{
    struct list *list;

    if ((list = malloc(sizeof(*list))) == NULL)
        return NULL;
    list->head = list->tail = NULL;
    list->len = 0;
    list->dup = NULL;
    list->free = NULL;
    list->match = NULL;
    return list;
}

/* Remove all the elements from the list without destroying the list itself. */
void listEmpty(list *list)
{
    unsigned long len;
    listNode *current, *next;

    current = list->head;
    len = list->len;
    while(len--) {
        next = current->next;
        if (list->free) list->free(current->value);
        free(current);
        current = next;
    }
    list->head = list->tail = NULL;
    list->len = 0;
}

/* Free the whole list.
 *
 * This function can't fail. */
void listRelease(list *list)
{
    listEmpty(list);
    free(list);
}

/* Add a new node to the list, to head, containing the specified 'value'
 * pointer as value.
 *
 * On error, NULL is returned and no operation is performed (i.e. the
 * list remains unaltered).
 * On success the 'list' pointer you pass to the function is returned. */
list *listAddNodeHead(list *list, void *value)
{
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = NULL;
        node->next = list->head;
        list->head->prev = node;
        list->head = node;
    }
    list->len++;
    return list;
}

/* Add a new node to the list, to tail, containing the specified 'value'
 * pointer as value.
 *
 * On error, NULL is returned and no operation is performed (i.e. the
 * list remains unaltered).
 * On success the 'list' pointer you pass to the function is returned. */
list *listAddNodeTail(list *list, void *value)
{
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = list->tail;
        node->next = NULL;
        list->tail->next = node;
        list->tail = node;
    }
    list->len++;
    return list;
}

list *listInsertNode(list *list, listNode *old_node, void *value, int after) {
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (after) {
        node->prev = old_node;
        node->next = old_node->next;
        if (list->tail == old_node) {
            list->tail = node;
        }
    } else {
        node->next = old_node;
        node->prev = old_node->prev;
        if (list->head == old_node) {
            list->head = node;
        }
    }
    if (node->prev != NULL) {
        node->prev->next = node;
    }
    if (node->next != NULL) {
        node->next->prev = node;
    }
    list->len++;
    return list;
}

/* Remove the specified node from the specified list.
 * It's up to the caller to free the private value of the node.
 *
 * This function can't fail. */
void listDelNode(list *list, listNode *node)
{
    if (node->prev)
        node->prev->next = node->next;
    else
        list->head = node->next;
    if (node->next)
        node->next->prev = node->prev;
    else
        list->tail = node->prev;
    if (list->free) list->free(node->value);
    free(node);
    list->len--;
}

/* Returns a list iterator 'iter'. After the initialization every
 * call to listNext() will return the next element of the list.
 *
 * This function can't fail. */
listIter *listGetIterator(list *list, int direction)
{
    listIter *iter;

    if ((iter = malloc(sizeof(*iter))) == NULL) return NULL;
    if (direction == AL_START_HEAD)
        iter->next = list->head;
    else
        iter->next = list->tail;
    iter->direction = direction;
    return iter;
}

/* Release the iterator memory */
void listReleaseIterator(listIter *iter) {
    free(iter);
}

/* Create an iterator in the list private iterator structure */
void listRewind(list *list, listIter *li) {
    li->next = list->head;
    li->direction = AL_START_HEAD;
}

void listRewindTail(list *list, listIter *li) {
    li->next = list->tail;
    li->direction = AL_START_TAIL;
}

/* Return the next element of an iterator.
 * It's valid to remove the currently returned element using
 * listDelNode(), but not to remove other elements.
 *
 * The function returns a pointer to the next element of the list,
 * or NULL if there are no more elements, so the classical usage patter
 * is:
 *
 * iter = listGetIterator(list,<direction>);
 * while ((node = listNext(iter)) != NULL) {
 *     doSomethingWith(listNodeValue(node));
 * }
 *
 * */
listNode *listNext(listIter *iter)
{
    listNode *current = iter->next;

    if (current != NULL) {
        if (iter->direction == AL_START_HEAD)
            iter->next = current->next;
        else
            iter->next = current->prev;
    }
    return current;
}

/* Duplicate the whole list. On out of memory NULL is returned.
 * On success a copy of the original list is returned.
 *
 * The 'Dup' method set with listSetDupMethod() function is used
 * to copy the node value. Otherwise the same pointer value of
 * the original node is used as value of the copied node.
 *
 * The original list both on success or error is never modified. */
list *listDup(list *orig)
{
    list *copy;
    listIter iter;
    listNode *node;

    if ((copy = listCreate()) == NULL)
        return NULL;
    copy->dup = orig->dup;
    copy->free = orig->free;
    copy->match = orig->match;
    listRewind(orig, &iter);
    while((node = listNext(&iter)) != NULL) {
        void *value;

        if (copy->dup) {
            value = copy->dup(node->value);
            if (value == NULL) {
                listRelease(copy);
                return NULL;
            }
        } else
            value = node->value;
        if (listAddNodeTail(copy, value) == NULL) {
            listRelease(copy);
            return NULL;
        }
    }
    return copy;
}

/* Search the list for a node matching a given key.
 * The match is performed using the 'match' method
 * set with listSetMatchMethod(). If no 'match' method
 * is set, the 'value' pointer of every node is directly
 * compared with the 'key' pointer.
 *
 * On success the first matching node pointer is returned
 * (search starts from head). If no matching node exists
 * NULL is returned. */
listNode *listSearchKey(list *list, void *key)
{
    listIter iter;
    listNode *node;

    listRewind(list, &iter);
    while((node = listNext(&iter)) != NULL) {
        if (list->match) {
            if (list->match(node->value, key)) {
                return node;
            }
        } else {
            if (key == node->value) {
                return node;
            }
        }
    }
    return NULL;
}

/* Return the element at the specified zero-based index
 * where 0 is the head, 1 is the element next to head
 * and so on. Negative integers are used in order to count
 * from the tail, -1 is the last element, -2 the penultimate
 * and so on. If the index is out of range NULL is returned. */
listNode *listIndex(list *list, long index) {
    listNode *n;

    if (index < 0) {
        index = (-index)-1;
        n = list->tail;
        while(index-- && n) n = n->prev;
    } else {
        n = list->head;
        while(index-- && n) n = n->next;
    }
    return n;
}

/* Rotate the list removing the tail node and inserting it to the head. */
void listRotate(list *list) {
    listNode *tail = list->tail;

    if (listLength(list) <= 1) return;

    /* Detach current tail */
    list->tail = tail->prev;
    list->tail->next = NULL;
    /* Move it as head */
    list->head->prev = tail;
    tail->prev = NULL;
    tail->next = list->head;
    list->head = tail;
}

/* Add all the elements of the list 'o' at the end of the
 * list 'l'. The list 'other' remains empty but otherwise valid. */
void listJoin(list *l, list *o) {
    if (o->head)
        o->head->prev = l->tail;

    if (l->tail)
        l->tail->next = o->head;
    else
        l->head = o->head;

    if (o->tail) l->tail = o->tail;
    l->len += o->len;

    /* Setup other as an empty list. */
    o->head = o->tail = NULL;
    o->len = 0;
}

14. array

pjproject-2.10pjlibincludepjarray.h

/* $Id$ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * 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 
 */
#ifndef __PJ_ARRAY_H__
#define __PJ_ARRAY_H__

/**
 * @file array.h
 * @brief PJLIB Array helper.
 */
#include <pj/types.h>

PJ_BEGIN_DECL

/**
 * @defgroup PJ_ARRAY Array helper.
 * @ingroup PJ_DS
 * @{
 *
 * This module provides helper to manipulate array of elements of any size.
 * It provides most used array operations such as insert, erase, and search.
 */

/**
 * Insert value to the array at the given position, and rearrange the
 * remaining nodes after the position.
 *
 * @param array        the array.
 * @param elem_size the size of the individual element.
 * @param count        the CURRENT number of elements in the array.
 * @param pos        the position where the new element is put.
 * @param value        the value to copy to the new element.
 */
PJ_DECL(void) pj_array_insert( void *array,
                   unsigned elem_size,
                   unsigned count,
                   unsigned pos,
                   const void *value);

/**
 * Erase a value from the array at given position, and rearrange the remaining
 * elements post the erased element.
 *
 * @param array        the array.
 * @param elem_size the size of the individual element.
 * @param count        the current number of elements in the array.
 * @param pos        the index/position to delete.
 */
PJ_DECL(void) pj_array_erase( void *array,
                  unsigned elem_size,
                  unsigned count,
                  unsigned pos);

/**
 * Search the first value in the array according to matching function.
 *
 * @param array        the array.
 * @param elem_size the individual size of the element.
 * @param count        the number of elements.
 * @param matching  the matching function, which MUST return PJ_SUCCESS if 
 *            the specified element match.
 * @param result    the pointer to the value found.
 *
 * @return        PJ_SUCCESS if value is found, otherwise the error code.
 */
PJ_DECL(pj_status_t) pj_array_find(   const void *array, 
                      unsigned elem_size, 
                      unsigned count, 
                      pj_status_t (*matching)(const void *value),
                      void **result);

/**
 * @}
 */

PJ_END_DECL


#endif    /* __PJ_ARRAY_H__ */

pjproject-2.10pjlibsrcpjarray.c

/* $Id$ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * 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 <pj/array.h>
#include <pj/string.h>
#include <pj/assert.h>
#include <pj/errno.h>

PJ_DEF(void) pj_array_insert( void *array,
                  unsigned elem_size,
                  unsigned count,
                  unsigned pos,
                  const void *value)
{
    if (count && pos < count) {
    pj_memmove( (char*)array + (pos+1)*elem_size,
            (char*)array + pos*elem_size,
            (count-pos)*elem_size);
    }
    pj_memmove((char*)array + pos*elem_size, value, elem_size);
}

PJ_DEF(void) pj_array_erase( void *array,
                 unsigned elem_size,
                 unsigned count,
                 unsigned pos)
{
    pj_assert(count != 0);
    if (pos < count-1) {
    pj_memmove( (char*)array + pos*elem_size,
            (char*)array + (pos+1)*elem_size,
            (count-pos-1)*elem_size);
    }
}

PJ_DEF(pj_status_t) pj_array_find( const void *array, 
                   unsigned elem_size, 
                   unsigned count, 
                   pj_status_t (*matching)(const void *value),
                   void **result)
{
    unsigned i;
    const char *char_array = (const char*)array;
    for (i=0; i<count; ++i) {
    if ( (*matching)(char_array) == PJ_SUCCESS) {
        if (result) {
        *result = (void*)char_array;
        }
        return PJ_SUCCESS;
    }
    char_array += elem_size;
    }
    return PJ_ENOTFOUND;
}

13. memery pool

12. base64

pjproject-2.10pjlib-utilincludepjlib-utilase64.h

/* $Id$ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * 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 
 */
#ifndef __PJLIB_UTIL_BASE64_H__
#define __PJLIB_UTIL_BASE64_H__

/**
 * @file base64.h
 * @brief Base64 encoding and decoding
 */

#include <pjlib-util/types.h>

PJ_BEGIN_DECL

/**
 * @defgroup PJLIB_UTIL_BASE64 Base64 Encoding/Decoding
 * @ingroup PJLIB_UTIL_ENCRYPTION
 * @{
 * This module implements base64 encoding and decoding.
 */

/**
 * Helper macro to calculate the approximate length required for base256 to
 * base64 conversion.
 */
#define PJ_BASE256_TO_BASE64_LEN(len)    (len * 4 / 3 + 3)

/**
 * Helper macro to calculate the approximage length required for base64 to
 * base256 conversion.
 */
#define PJ_BASE64_TO_BASE256_LEN(len)    (len * 3 / 4)


/**
 * Encode a buffer into base64 encoding.
 *
 * @param input        The input buffer.
 * @param in_len    Size of the input buffer.
 * @param output    Output buffer. Caller must allocate this buffer with
 *            the appropriate size.
 * @param out_len   On entry, it specifies the length of the output buffer. 
 *            Upon return, this will be filled with the actual
 *            length of the output buffer.
 *
 * @return        PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pj_base64_encode(const pj_uint8_t *input, int in_len,
                     char *output, int *out_len);


/**
 * Decode base64 string.
 *
 * @param input        Input string.
 * @param out        Buffer to store the output. Caller must allocate
 *            this buffer with the appropriate size.
 * @param out_len   On entry, it specifies the length of the output buffer. 
 *            Upon return, this will be filled with the actual
 *            length of the output.
 */
PJ_DECL(pj_status_t) pj_base64_decode(const pj_str_t *input, 
                      pj_uint8_t *out, int *out_len);



/**
 * @}
 */

PJ_END_DECL


#endif    /* __PJLIB_UTIL_BASE64_H__ */

pjproject-2.10pjlib-utilsrcpjlib-utilase64.c

/* $Id$ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * 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 <pjlib-util/base64.h>
#include <pj/assert.h>
#include <pj/errno.h>

#define INV        -1
#define PADDING        '='

static const char base64_char[] = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', '+', '/' 
};

static int base256_char(char c)
{
    if (c >= 'A' && c <= 'Z')
    return (c - 'A');
    else if (c >= 'a' && c <= 'z')
    return (c - 'a' + 26);
    else if (c >= '0' && c <= '9')
    return (c - '0' + 52);
    else if (c == '+')
    return (62);
    else if (c == '/')
    return (63);
    else {
    /* It *may* happen on bad input, so this is not a good idea.
     * pj_assert(!"Should not happen as '=' should have been filtered");
     */
    return INV;
    }
}


static void base256to64(pj_uint8_t c1, pj_uint8_t c2, pj_uint8_t c3, 
            int padding, char *output)
{
    *output++ = base64_char[c1>>2];
    *output++ = base64_char[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
    switch (padding) {
    case 0:
    *output++ = base64_char[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
    *output = base64_char[c3 & 0x3F];
    break;
    case 1:
    *output++ = base64_char[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
    *output = PADDING;
    break;
    case 2:
    default:
    *output++ = PADDING;
    *output = PADDING;
    break;
    }
}


PJ_DEF(pj_status_t) pj_base64_encode(const pj_uint8_t *input, int in_len,
                     char *output, int *out_len)
{
    const pj_uint8_t *pi = input;
    pj_uint8_t c1, c2, c3;
    int i = 0;
    char *po = output;

    PJ_ASSERT_RETURN(input && output && out_len, PJ_EINVAL);
    PJ_ASSERT_RETURN(*out_len >= PJ_BASE256_TO_BASE64_LEN(in_len), 
             PJ_ETOOSMALL);

    while (i < in_len) {
    c1 = *pi++;
    ++i;

    if (i == in_len) {
        base256to64(c1, 0, 0, 2, po);
        po += 4;
        break;
    } else {
        c2 = *pi++;
        ++i;

        if (i == in_len) {
        base256to64(c1, c2, 0, 1, po);
        po += 4;
        break;
        } else {
        c3 = *pi++;
        ++i;
        base256to64(c1, c2, c3, 0, po);
        }
    }

    po += 4;
    }

    *out_len = (int)(po - output);
    return PJ_SUCCESS;
}


PJ_DEF(pj_status_t) pj_base64_decode(const pj_str_t *input, 
                     pj_uint8_t *out, int *out_len)
{
    const char *buf;
    int len;
    int i, j, k;
    int c[4];

    PJ_ASSERT_RETURN(input && out && out_len, PJ_EINVAL);

    buf = input->ptr;
    len = (int)input->slen;
    while (len && buf[len-1] == '=')
    --len;

    PJ_ASSERT_RETURN(*out_len >= PJ_BASE64_TO_BASE256_LEN(len), 
             PJ_ETOOSMALL);

    for (i=0, j=0; i<len; ) {
    /* Fill up c, silently ignoring invalid characters */
    for (k=0; k<4 && i<len; ++k) {
        do {
        c[k] = base256_char(buf[i++]);
        } while (c[k]==INV && i<len);
    }

    if (k<4) {
        if (k > 1) {
        out[j++] = (pj_uint8_t)((c[0]<<2) | ((c[1] & 0x30)>>4));
        if (k > 2) {
            out[j++] = (pj_uint8_t)
                   (((c[1] & 0x0F)<<4) | ((c[2] & 0x3C)>>2));
        }
        }
        break;
    }

    out[j++] = (pj_uint8_t)((c[0]<<2) | ((c[1] & 0x30)>>4));
    out[j++] = (pj_uint8_t)(((c[1] & 0x0F)<<4) | ((c[2] & 0x3C)>>2));
    out[j++] = (pj_uint8_t)(((c[2] & 0x03)<<6) | (c[3] & 0x3F));
    }

    pj_assert(j <= *out_len);
    *out_len = j;

    return PJ_SUCCESS;
}

11. color_table[]

ffmpeg-4.1/libavutil/parseutils.c

typedef struct {
    const char *name;            ///< a string representing the name of the color
    uint8_t     rgb_color[3];    ///< RGB values for the color
} ColorEntry;

static const ColorEntry color_table[] = {
    { "AliceBlue",            { 0xF0, 0xF8, 0xFF } },
    { "AntiqueWhite",         { 0xFA, 0xEB, 0xD7 } },
    { "Aqua",                 { 0x00, 0xFF, 0xFF } },
    { "Aquamarine",           { 0x7F, 0xFF, 0xD4 } },
    { "Azure",                { 0xF0, 0xFF, 0xFF } },
    { "Beige",                { 0xF5, 0xF5, 0xDC } },
    { "Bisque",               { 0xFF, 0xE4, 0xC4 } },
    { "Black",                { 0x00, 0x00, 0x00 } },
    { "BlanchedAlmond",       { 0xFF, 0xEB, 0xCD } },
    { "Blue",                 { 0x00, 0x00, 0xFF } },
    { "BlueViolet",           { 0x8A, 0x2B, 0xE2 } },
    { "Brown",                { 0xA5, 0x2A, 0x2A } },
    { "BurlyWood",            { 0xDE, 0xB8, 0x87 } },
    { "CadetBlue",            { 0x5F, 0x9E, 0xA0 } },
    { "Chartreuse",           { 0x7F, 0xFF, 0x00 } },
    { "Chocolate",            { 0xD2, 0x69, 0x1E } },
    { "Coral",                { 0xFF, 0x7F, 0x50 } },
    { "CornflowerBlue",       { 0x64, 0x95, 0xED } },
    { "Cornsilk",             { 0xFF, 0xF8, 0xDC } },
    { "Crimson",              { 0xDC, 0x14, 0x3C } },
    { "Cyan",                 { 0x00, 0xFF, 0xFF } },
    { "DarkBlue",             { 0x00, 0x00, 0x8B } },
    { "DarkCyan",             { 0x00, 0x8B, 0x8B } },
    { "DarkGoldenRod",        { 0xB8, 0x86, 0x0B } },
    { "DarkGray",             { 0xA9, 0xA9, 0xA9 } },
    { "DarkGreen",            { 0x00, 0x64, 0x00 } },
    { "DarkKhaki",            { 0xBD, 0xB7, 0x6B } },
    { "DarkMagenta",          { 0x8B, 0x00, 0x8B } },
    { "DarkOliveGreen",       { 0x55, 0x6B, 0x2F } },
    { "Darkorange",           { 0xFF, 0x8C, 0x00 } },
    { "DarkOrchid",           { 0x99, 0x32, 0xCC } },
    { "DarkRed",              { 0x8B, 0x00, 0x00 } },
    { "DarkSalmon",           { 0xE9, 0x96, 0x7A } },
    { "DarkSeaGreen",         { 0x8F, 0xBC, 0x8F } },
    { "DarkSlateBlue",        { 0x48, 0x3D, 0x8B } },
    { "DarkSlateGray",        { 0x2F, 0x4F, 0x4F } },
    { "DarkTurquoise",        { 0x00, 0xCE, 0xD1 } },
    { "DarkViolet",           { 0x94, 0x00, 0xD3 } },
    { "DeepPink",             { 0xFF, 0x14, 0x93 } },
    { "DeepSkyBlue",          { 0x00, 0xBF, 0xFF } },
    { "DimGray",              { 0x69, 0x69, 0x69 } },
    { "DodgerBlue",           { 0x1E, 0x90, 0xFF } },
    { "FireBrick",            { 0xB2, 0x22, 0x22 } },
    { "FloralWhite",          { 0xFF, 0xFA, 0xF0 } },
    { "ForestGreen",          { 0x22, 0x8B, 0x22 } },
    { "Fuchsia",              { 0xFF, 0x00, 0xFF } },
    { "Gainsboro",            { 0xDC, 0xDC, 0xDC } },
    { "GhostWhite",           { 0xF8, 0xF8, 0xFF } },
    { "Gold",                 { 0xFF, 0xD7, 0x00 } },
    { "GoldenRod",            { 0xDA, 0xA5, 0x20 } },
    { "Gray",                 { 0x80, 0x80, 0x80 } },
    { "Green",                { 0x00, 0x80, 0x00 } },
    { "GreenYellow",          { 0xAD, 0xFF, 0x2F } },
    { "HoneyDew",             { 0xF0, 0xFF, 0xF0 } },
    { "HotPink",              { 0xFF, 0x69, 0xB4 } },
    { "IndianRed",            { 0xCD, 0x5C, 0x5C } },
    { "Indigo",               { 0x4B, 0x00, 0x82 } },
    { "Ivory",                { 0xFF, 0xFF, 0xF0 } },
    { "Khaki",                { 0xF0, 0xE6, 0x8C } },
    { "Lavender",             { 0xE6, 0xE6, 0xFA } },
    { "LavenderBlush",        { 0xFF, 0xF0, 0xF5 } },
    { "LawnGreen",            { 0x7C, 0xFC, 0x00 } },
    { "LemonChiffon",         { 0xFF, 0xFA, 0xCD } },
    { "LightBlue",            { 0xAD, 0xD8, 0xE6 } },
    { "LightCoral",           { 0xF0, 0x80, 0x80 } },
    { "LightCyan",            { 0xE0, 0xFF, 0xFF } },
    { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
    { "LightGreen",           { 0x90, 0xEE, 0x90 } },
    { "LightGrey",            { 0xD3, 0xD3, 0xD3 } },
    { "LightPink",            { 0xFF, 0xB6, 0xC1 } },
    { "LightSalmon",          { 0xFF, 0xA0, 0x7A } },
    { "LightSeaGreen",        { 0x20, 0xB2, 0xAA } },
    { "LightSkyBlue",         { 0x87, 0xCE, 0xFA } },
    { "LightSlateGray",       { 0x77, 0x88, 0x99 } },
    { "LightSteelBlue",       { 0xB0, 0xC4, 0xDE } },
    { "LightYellow",          { 0xFF, 0xFF, 0xE0 } },
    { "Lime",                 { 0x00, 0xFF, 0x00 } },
    { "LimeGreen",            { 0x32, 0xCD, 0x32 } },
    { "Linen",                { 0xFA, 0xF0, 0xE6 } },
    { "Magenta",              { 0xFF, 0x00, 0xFF } },
    { "Maroon",               { 0x80, 0x00, 0x00 } },
    { "MediumAquaMarine",     { 0x66, 0xCD, 0xAA } },
    { "MediumBlue",           { 0x00, 0x00, 0xCD } },
    { "MediumOrchid",         { 0xBA, 0x55, 0xD3 } },
    { "MediumPurple",         { 0x93, 0x70, 0xD8 } },
    { "MediumSeaGreen",       { 0x3C, 0xB3, 0x71 } },
    { "MediumSlateBlue",      { 0x7B, 0x68, 0xEE } },
    { "MediumSpringGreen",    { 0x00, 0xFA, 0x9A } },
    { "MediumTurquoise",      { 0x48, 0xD1, 0xCC } },
    { "MediumVioletRed",      { 0xC7, 0x15, 0x85 } },
    { "MidnightBlue",         { 0x19, 0x19, 0x70 } },
    { "MintCream",            { 0xF5, 0xFF, 0xFA } },
    { "MistyRose",            { 0xFF, 0xE4, 0xE1 } },
    { "Moccasin",             { 0xFF, 0xE4, 0xB5 } },
    { "NavajoWhite",          { 0xFF, 0xDE, 0xAD } },
    { "Navy",                 { 0x00, 0x00, 0x80 } },
    { "OldLace",              { 0xFD, 0xF5, 0xE6 } },
    { "Olive",                { 0x80, 0x80, 0x00 } },
    { "OliveDrab",            { 0x6B, 0x8E, 0x23 } },
    { "Orange",               { 0xFF, 0xA5, 0x00 } },
    { "OrangeRed",            { 0xFF, 0x45, 0x00 } },
    { "Orchid",               { 0xDA, 0x70, 0xD6 } },
    { "PaleGoldenRod",        { 0xEE, 0xE8, 0xAA } },
    { "PaleGreen",            { 0x98, 0xFB, 0x98 } },
    { "PaleTurquoise",        { 0xAF, 0xEE, 0xEE } },
    { "PaleVioletRed",        { 0xD8, 0x70, 0x93 } },
    { "PapayaWhip",           { 0xFF, 0xEF, 0xD5 } },
    { "PeachPuff",            { 0xFF, 0xDA, 0xB9 } },
    { "Peru",                 { 0xCD, 0x85, 0x3F } },
    { "Pink",                 { 0xFF, 0xC0, 0xCB } },
    { "Plum",                 { 0xDD, 0xA0, 0xDD } },
    { "PowderBlue",           { 0xB0, 0xE0, 0xE6 } },
    { "Purple",               { 0x80, 0x00, 0x80 } },
    { "Red",                  { 0xFF, 0x00, 0x00 } },
    { "RosyBrown",            { 0xBC, 0x8F, 0x8F } },
    { "RoyalBlue",            { 0x41, 0x69, 0xE1 } },
    { "SaddleBrown",          { 0x8B, 0x45, 0x13 } },
    { "Salmon",               { 0xFA, 0x80, 0x72 } },
    { "SandyBrown",           { 0xF4, 0xA4, 0x60 } },
    { "SeaGreen",             { 0x2E, 0x8B, 0x57 } },
    { "SeaShell",             { 0xFF, 0xF5, 0xEE } },
    { "Sienna",               { 0xA0, 0x52, 0x2D } },
    { "Silver",               { 0xC0, 0xC0, 0xC0 } },
    { "SkyBlue",              { 0x87, 0xCE, 0xEB } },
    { "SlateBlue",            { 0x6A, 0x5A, 0xCD } },
    { "SlateGray",            { 0x70, 0x80, 0x90 } },
    { "Snow",                 { 0xFF, 0xFA, 0xFA } },
    { "SpringGreen",          { 0x00, 0xFF, 0x7F } },
    { "SteelBlue",            { 0x46, 0x82, 0xB4 } },
    { "Tan",                  { 0xD2, 0xB4, 0x8C } },
    { "Teal",                 { 0x00, 0x80, 0x80 } },
    { "Thistle",              { 0xD8, 0xBF, 0xD8 } },
    { "Tomato",               { 0xFF, 0x63, 0x47 } },
    { "Turquoise",            { 0x40, 0xE0, 0xD0 } },
    { "Violet",               { 0xEE, 0x82, 0xEE } },
    { "Wheat",                { 0xF5, 0xDE, 0xB3 } },
    { "White",                { 0xFF, 0xFF, 0xFF } },
    { "WhiteSmoke",           { 0xF5, 0xF5, 0xF5 } },
    { "Yellow",               { 0xFF, 0xFF, 0x00 } },
    { "YellowGreen",          { 0x9A, 0xCD, 0x32 } },
};

10. hardware operations wraper

/**
 * Sound stream operations.
 */
typedef struct pjmedia_aud_stream_op
{
    /**
     * See #pjmedia_aud_stream_get_param()
     */
    pj_status_t (*get_param)(pjmedia_aud_stream *strm,
                 pjmedia_aud_param *param);

    /**
     * See #pjmedia_aud_stream_get_cap()
     */
    pj_status_t (*get_cap)(pjmedia_aud_stream *strm,
               pjmedia_aud_dev_cap cap,
               void *value);

    /**
     * See #pjmedia_aud_stream_set_cap()
     */
    pj_status_t (*set_cap)(pjmedia_aud_stream *strm,
               pjmedia_aud_dev_cap cap,
               const void *value);

    /**
     * See #pjmedia_aud_stream_start()
     */
    pj_status_t (*start)(pjmedia_aud_stream *strm);

    /**
     * See #pjmedia_aud_stream_stop().
     */
    pj_status_t (*stop)(pjmedia_aud_stream *strm);

    /**
     * See #pjmedia_aud_stream_destroy().
     */
    pj_status_t (*destroy)(pjmedia_aud_stream *strm);

} pjmedia_aud_stream_op;

static pjmedia_aud_stream_op alsa_stream_op =
{
    &alsa_stream_get_param,
    &alsa_stream_get_cap,
    &alsa_stream_set_cap,
    &alsa_stream_start,
    &alsa_stream_stop,
    &alsa_stream_destroy
};

9. PJSIP-SIMPLE's own error codes/messages

pjproject-2.10pjlib-utilsrcpjlib-utilerrno.c

/* $Id$ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * 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 <pjlib-util/errno.h>
#include <pjlib-util/types.h>
#include <pj/assert.h>
#include <pj/string.h>



/* PJLIB_UTIL's own error codes/messages 
 * MUST KEEP THIS ARRAY SORTED!!
 * Message must be limited to 64 chars!
 */
#if defined(PJ_HAS_ERROR_STRING) && PJ_HAS_ERROR_STRING!=0
static const struct 
{
    int code;
    const char *msg;
} err_str[] = 
{
    /* STUN errors */
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNRESOLVE,    "Unable to resolve STUN server" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNINMSGTYPE,    "Unknown STUN message type" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNINMSGLEN,    "Invalid STUN message length" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNINATTRLEN,    "STUN attribute length error" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNINATTRTYPE,    "Invalid STUN attribute type" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNININDEX,    "Invalid STUN server/socket index" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNOBINDRES,    "No STUN binding response in the message" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNRECVERRATTR,    "Received STUN error attribute" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNOMAP,    "No STUN mapped address attribute" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNOTRESPOND,    "Received no response from STUN server" ),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNSYMMETRIC,    "Symetric NAT detected by STUN" ),

    /* XML errors */
    PJ_BUILD_ERR( PJLIB_UTIL_EINXML,        "Invalid XML message" ),

    /* JSON errors */
    PJ_BUILD_ERR( PJLIB_UTIL_EINJSON,        "Invalid JSON document" ),

    /* DNS errors */
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSQRYTOOSMALL,    "DNS query packet buffer is too small"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSINSIZE,    "Invalid DNS packet length"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSINCLASS,    "Invalid DNS class"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSINNAMEPTR,    "Invalid DNS name pointer"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSINNSADDR,    "Invalid DNS nameserver address"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSNONS,        "No nameserver is in DNS resolver"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSNOWORKINGNS,    "No working DNS nameserver"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSNOANSWERREC,    "No answer record in the DNS response"),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNSINANSWER,    "Invalid DNS answer"),

    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_FORMERR,    "DNS "Format error""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_SERVFAIL,    "DNS "Server failure""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_NXDOMAIN,    "DNS "Name Error""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_NOTIMPL,    "DNS "Not Implemented""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_REFUSED,    "DNS "Refused""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_YXDOMAIN,    "DNS "The name exists""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_YXRRSET,    "DNS "The RRset (name, type) exists""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_NXRRSET,    "DNS "The RRset (name, type) does not exist""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_NOTAUTH,    "DNS "Not authorized""),
    PJ_BUILD_ERR( PJLIB_UTIL_EDNS_NOTZONE,    "DNS "The zone specified is not a zone""),

    /* STUN */
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNTOOMANYATTR,    "Too many STUN attributes"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNUNKNOWNATTR,    "Unknown STUN attribute"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNINADDRLEN,    "Invalid STUN socket address length"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNIPV6NOTSUPP,    "STUN IPv6 attribute not supported"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNOTRESPONSE,    "Expecting STUN response message"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNINVALIDID,    "STUN transaction ID mismatch"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNOHANDLER,    "Unable to find STUN handler for the request"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNMSGINTPOS,    "Found non-FINGERPRINT attr. after MESSAGE-INTEGRITY"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNFINGERPOS,    "Found STUN attribute after FINGERPRINT"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNOUSERNAME,    "Missing STUN USERNAME attribute"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNMSGINT,    "Missing/invalid STUN MESSAGE-INTEGRITY attribute"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNDUPATTR,    "Found duplicate STUN attribute"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNOREALM,    "Missing STUN REALM attribute"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNNONCE,    "Missing/stale STUN NONCE attribute value"),
    PJ_BUILD_ERR( PJLIB_UTIL_ESTUNTSXFAILED,    "STUN transaction terminates with failure"),

    /* HTTP Client */
    PJ_BUILD_ERR( PJLIB_UTIL_EHTTPINURL,    "Invalid URL format"),
    PJ_BUILD_ERR( PJLIB_UTIL_EHTTPINPORT,    "Invalid URL port number"),
    PJ_BUILD_ERR( PJLIB_UTIL_EHTTPINCHDR,    "Incomplete response header received"),
    PJ_BUILD_ERR( PJLIB_UTIL_EHTTPINSBUF,    "Insufficient buffer"),
    PJ_BUILD_ERR( PJLIB_UTIL_EHTTPLOST,            "Connection lost"),

    /* CLI */
    PJ_BUILD_ERR( PJ_CLI_EEXIT,                    "Exit current session"),
    PJ_BUILD_ERR( PJ_CLI_EMISSINGARG,            "Missing argument"),
    PJ_BUILD_ERR( PJ_CLI_ETOOMANYARGS,            "Too many arguments"),
    PJ_BUILD_ERR( PJ_CLI_EINVARG,            "Invalid argument"),
    PJ_BUILD_ERR( PJ_CLI_EBADNAME,            "Command name already exists"),
    PJ_BUILD_ERR( PJ_CLI_EBADID,            "Command id already exists"),
    PJ_BUILD_ERR( PJ_CLI_EBADXML,            "Invalid XML format"),
    PJ_BUILD_ERR( PJ_CLI_ETELNETLOST,            "Connection lost"),
};
#endif    /* PJ_HAS_ERROR_STRING */


/*
 * pjlib_util_strerror()
 */
pj_str_t pjlib_util_strerror(pj_status_t statcode, 
                 char *buf, pj_size_t bufsize )
{
    pj_str_t errstr;

#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)

    if (statcode >= PJLIB_UTIL_ERRNO_START && 
    statcode < PJLIB_UTIL_ERRNO_START + PJ_ERRNO_SPACE_SIZE)
    {
    /* Find the error in the table.
     * Use binary search!
     */
    int first = 0;
    int n = PJ_ARRAY_SIZE(err_str);

    while (n > 0) {
        int half = n/2;
        int mid = first + half;

        if (err_str[mid].code < statcode) {
        first = mid+1;
        n -= (half+1);
        } else if (err_str[mid].code > statcode) {
        n = half;
        } else {
        first = mid;
        break;
        }
    }


    if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) {
        pj_str_t msg;
        
        msg.ptr = (char*)err_str[first].msg;
        msg.slen = pj_ansi_strlen(err_str[first].msg);

        errstr.ptr = buf;
        pj_strncpy_with_null(&errstr, &msg, bufsize);
        return errstr;

    } 
    }

#endif    /* PJ_HAS_ERROR_STRING */


    /* Error not found. */
    errstr.ptr = buf;
    errstr.slen = pj_ansi_snprintf(buf, bufsize, 
                   "Unknown pjlib-util error %d",
                   statcode);
    if (errstr.slen < 1 || errstr.slen >= (pj_ssize_t)bufsize)
    errstr.slen = bufsize - 1;
    return errstr;
}


PJ_DEF(pj_status_t) pjlib_util_init(void)
{
    pj_status_t status;
    
    status = pj_register_strerror(PJLIB_UTIL_ERRNO_START, 
                  PJ_ERRNO_SPACE_SIZE, 
                  &pjlib_util_strerror);
    pj_assert(status == PJ_SUCCESS);

    return status;
}

8. define our own boolean type

/* define our own boolean type */
typedef int pj_bool_t;
#define true ((pj_bool_t)1)
#define false ((pj_bool_t)0)

7. getopt_long(bluez/Sdptool.c)

static struct {
    char *cmd;
    int (*func)(int argc, char **argv);
    char *doc;
} command[] = {
    { "search",  cmd_search,      "Search for a service"          },
    { "browse",  cmd_browse,      "Browse all available services" },
    { "records", cmd_records,     "Request all records"           },
    { "add",     cmd_add,         "Add local service"             },
    { "del",     cmd_del,         "Delete local service"          },
    { "get",     cmd_get,         "Get local service"             },
    { "setattr", cmd_setattr,     "Set/Add attribute to a SDP record"          },
    { "setseq",  cmd_setseq,      "Set/Add attribute sequence to a SDP record" },
    { 0, 0, 0 }
};

static void usage(void)
{
    int i, pos = 0;

    printf("sdptool - SDP tool v%s
", VERSION);
    printf("Usage:
"
        "	sdptool [options] <command> [command parameters]
");
    printf("Options:
"
        "	-h		Display help
"
        "	-i		Specify source interface
");

    printf("Commands:
");
    for (i = 0; command[i].cmd; i++)
        printf("	%-4s		%s
", command[i].cmd, command[i].doc);

    printf("
Services:
	");
    for (i = 0; service[i].name; i++) {
        printf("%s ", service[i].name);
        pos += strlen(service[i].name) + 1;
        if (pos > 60) {
            printf("
	");
            pos = 0;
        }
    }
    printf("
");
}

static struct option main_options[] = {
    { "help",    0, 0, 'h' },
    { "device",    1, 0, 'i' },
    { 0, 0, 0, 0 }
};

int main(int argc, char *argv[])
{
    int i, opt;

    bacpy(&interface, BDADDR_ANY);

    while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
        switch(opt) {
        case 'i':
            if (!strncmp(optarg, "hci", 3))
                hci_devba(atoi(optarg + 3), &interface);
            else
                str2ba(optarg, &interface);
            break;

        case 'h':
            usage();
            exit(0);

        default:
            exit(1);
        }
    }

    argc -= optind;
    argv += optind;
    optind = 0;

    if (argc < 1) {
        usage();
        exit(1);
    }

    for (i = 0; command[i].cmd; i++)
        if (strncmp(command[i].cmd, argv[0], 4) == 0)
            return command[i].func(argc, argv);

    return 1;
}

6. fgets + stdin (human-computer interaction)

static pj_bool_t simple_input(const char *title, char *buf, pj_size_t len)
{
    char *p;

    printf("%s (empty to cancel): ", title); fflush(stdout);
    if (fgets(buf, (int)len, stdin) == NULL)
    return PJ_FALSE;

    /* Remove trailing newlines. */
    for (p=buf; ; ++p) {
    if (*p=='
' || *p=='
') *p='';
    else if (!*p) break;
    }

    if (!*buf)
    return PJ_FALSE;

    return PJ_TRUE;
}

example:

static void ui_answer_call()
{
    pjsua_call_info call_info;
    char buf[128];
    pjsua_msg_data msg_data_;

    if (current_call != -1) {
    pjsua_call_get_info(current_call, &call_info);
    } else {
    /* Make compiler happy */
    call_info.role = PJSIP_ROLE_UAC;
    call_info.state = PJSIP_INV_STATE_DISCONNECTED;
    }

    if (current_call == -1 ||
    call_info.role != PJSIP_ROLE_UAS ||
    call_info.state >= PJSIP_INV_STATE_CONNECTING)
    {
    puts("No pending incoming call");
    fflush(stdout);
    return;

    } else {
    int st_code;
    char contact[120];
    pj_str_t hname = { "Contact", 7 };
    pj_str_t hvalue;
    pjsip_generic_string_hdr hcontact;

    if (!simple_input("Answer with code (100-699)", buf, sizeof(buf)))
        return;

    st_code = my_atoi(buf);
    if (st_code < 100)
        return;

    pjsua_msg_data_init(&msg_data_);

    if (st_code/100 == 3) {
        if (!simple_input("Enter URL to be put in Contact",
        contact, sizeof(contact)))
        return;
        hvalue = pj_str(contact);
        pjsip_generic_string_hdr_init2(&hcontact, &hname, &hvalue);

        pj_list_push_back(&msg_data_.hdr_list, &hcontact);
    }

    /*
    * Must check again!
    * Call may have been disconnected while we're waiting for
    * keyboard input.
    */
    if (current_call == -1) {
        puts("Call has been disconnected");
        fflush(stdout);
        return;
    }

    pjsua_call_answer2(current_call, &call_opt, st_code, NULL, &msg_data_);
    }
}
5. 指针的应用
1)用指针来改变变量/指针的值
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i = 9;
    int* p = &i;

    *p = 0xb;
    //用指针改变一个变量的值
    printf("i=0x%x
",i);
    printf("p=0x%x
",p);

    int** q = &p;

    **q = 0xc;

    //用二级指针改变一个变量的值
    printf("i=0x%x
",i);
    printf("p=0x%x
",p);

    *q = (int *)0xFFFFFFFF;
    //用二级指针改变一个指针的值
    printf("i=0x%x
",i);
    printf("p=0x%x
",p);

    return 0;
}

2)用函数来改变指针的值

# include <stdio.h>
void f(int ** q);
int main(void)
{
    int i = 9;
    int * p = &i;
    printf("p=0x%x
", p);
    f(&p);
    printf("p=0x%x
", p);

    return 0;
}
void f(int ** q)
{
    *q = (int *)0xFFFFFFFF;
}

4. union与数据的拆分与合并以及大小端的判断

1) 将int型的i拆分成4字节char型的c

#include<stdio.h>  
union var{  
        char c[4];  
        int i;  
};  
  
int main(){  
        union var data;  
        data.i = 0x11020304; 
        printf("%x
",data.c[0]);
printf("%x ",data.c[1]);
printf("%x ",data.c[2]);
     printf("%x ",data.c[3]);
     return 0;
}

2) 合并就是反过来

#include<stdio.h>  
union var{  
        char c[4];  
        int i;  
};  
  
int main(){  
        union var data;  
        data.c[0] = 0x04;
        data.c[1] = 0x03;
        data.c[2] = 0x02;  
        data.c[3] = 0x11;  
        printf("%x
",data.i); 
     return 0; }

3) 大小端的判断

#include<stdio.h>  
union var{  
        char c[4];  
        int i;  
};  
  
int main(){  
        union var data;  
        data.i = 0x11020304; 
        printf("%x
",data.c[0]);
        printf("%x
",data.c[1]);
        printf("%x
",data.c[2]);
     printf("%x
",data.c[3]);

        if( data.c[0] == 0x11 )
        {
          printf("Systerm is BigEndian");
        }
     return 0; 
}

3. 连接符#的应用

1) 连接数值类型用双#

#include <stdio.h>

#define   COMB(a,b,c)   a##b##c
  
void main()
{    
       printf("%d
",COMB(1,2,3));  
}

2) 连接字符类型用单#

#include <stdio.h>

#define   CATSTR(n)   "abcd"#n  

void main()  
{  
        printf("%s
",CATSTR(100));  
}

2. 函数指针散转

//预存的APP响应
void (*CmdCallbackArray[APP_CMD_MAX])(uint8_t *para) = {
    0 ,
    FirewareManageCallback , // FirewareManage = 1
    DataSyncCallback ,
    SetCmdCallback,
    HintCmdCallback,
    0,
    BindCallback,
    FactoryTestCallback,
    LogCtrlCallback

};

bool  App_Data_L1_DataParse( uint8_t *L1_Packet,uint8_t *L1_Payload){
  bool ret=true;

  uint8_t para[60] = {0};
  uint16_t L2_len = 0;
  uint16_t check_sum = 0;
  L2_len =((((uint16_t)L1_Packet[5])<<8)|((uint16_t)L1_Packet[6]));

  check_sum = CRC_calc(&L1_Packet[9] , &L1_Packet[9+L2_len]);

  if( ( (((uint16_t)L1_Packet[7])<<8)|((uint16_t)L1_Packet[8]) ) ==  check_sum )
  {
    //正常接收,进入L2_Command_Content
    para[0] = L1_Packet[2];
    memcpy(&para[1],&L1_Packet[10],L2_len-1);
    CmdCallbackArray[L1_Packet[9]](para);
  }
  return ret;
}

1. 函数指针收敛

typedef struct task
{
    pthread_t id;
    int fd;
    uint8_t buf[1024];
    int size;
}task_t;

void (*task_array[])(int fd, uint8_t* buf, uint8_t size) = {
    qx_raw ,
    qx_raw_2_ubx ,
    qx_raw_2_ubx_zhd ,
    zhd_raw,
    zhd_raw_2_ubx,
    zhd_raw_2_ubx_zhd,
};

static void* 
task_done(void *arg)
{
    task_t task = *(task_t*)(arg);
    int i = 0;
    while(task_array[i] != NULL){
        (task_array[i])(task.fd, task.buf, task.size); 
        i++;
    }
    printf ("task %d done !
", task.fd);     
}
原文地址:https://www.cnblogs.com/dong1/p/13796692.html