util.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright STREAMIT BV, 2010.
  3. *
  4. * Project : SIR
  5. * Module : Util
  6. * File name $Workfile: Util.c $
  7. * Last Save $Date: 2006/05/11 9:53:22 $
  8. * $Revision: 0.1 $
  9. * Creation Date : 2006/05/11 9:53:22
  10. *
  11. * Description : Utility functions for the SIR project
  12. *
  13. */
  14. #define LOG_MODULE LOG_UTIL_MODULE
  15. /*--------------------------------------------------------------------------*/
  16. /* Include files */
  17. /*--------------------------------------------------------------------------*/
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <sys/heap.h>
  21. //#pragma text:appcode
  22. #include "system.h"
  23. #include "log.h"
  24. #include "util.h"
  25. /*--------------------------------------------------------------------------*/
  26. /* Constant definitions */
  27. /*--------------------------------------------------------------------------*/
  28. #ifdef DEBUG
  29. //#define UTIL_DEBUG
  30. #endif /* #ifdef DEBUG */
  31. /*--------------------------------------------------------------------------*/
  32. /* Type declarations */
  33. /*--------------------------------------------------------------------------*/
  34. /*--------------------------------------------------------------------------*/
  35. /* Local variables */
  36. /*--------------------------------------------------------------------------*/
  37. /*--------------------------------------------------------------------------*/
  38. /* Global variables */
  39. /*--------------------------------------------------------------------------*/
  40. /*--------------------------------------------------------------------------*/
  41. /* Local functions */
  42. /*--------------------------------------------------------------------------*/
  43. /*--------------------------------------------------------------------------*/
  44. /* Global functions */
  45. /*--------------------------------------------------------------------------*/
  46. /*!
  47. * \brief Allocate memory.
  48. *
  49. * \param unSize [in] Amount of memory to allocate.
  50. *
  51. * \return pointer to the allocated memory.
  52. * NULL if there is no memory left or you requested 0 size.
  53. */
  54. void *MyMalloc(unsigned int unSize)
  55. {
  56. void *pResult = NULL;
  57. if ((unSize != 0) &&
  58. ((pResult = NutHeapAlloc(unSize)) == NULL))
  59. {
  60. LogMsg_P(LOG_ERR, PSTR("No memory [%u]"), unSize);
  61. }
  62. return (pResult);
  63. }
  64. /*!
  65. * \brief Create a copy of a string.
  66. *
  67. * Allocates sufficient memory from heap for a copy of the string
  68. * and does the copy.
  69. *
  70. * \param str [in] Pointer to the string to copy.
  71. *
  72. * \return A pointer to the new string.
  73. * NULL if allocating memory failed.
  74. */
  75. char *strdup(CONST char *str)
  76. {
  77. char *copy = NULL;
  78. if (str != NULL)
  79. {
  80. size_t siz = strlen(str) + 1;
  81. if ((copy = MyMalloc(siz)) != NULL)
  82. {
  83. memcpy(copy, str, siz);
  84. }
  85. }
  86. return (copy);
  87. }
  88. /*!
  89. * \brief Allocate new memory if needed.
  90. *
  91. * Checks if a memory block is large enough to hold additional data.
  92. * If it is not, the buffer is reallocated so it can hold the additional data.
  93. *
  94. * \param ppcBuf [in,out] Address of a pointer to a memory block.
  95. * \param punBufSize [in,out] The currently allocated size, [out] the new blocksize
  96. * \param unBufInUse [in] Currently in use.
  97. * \param unSizeNeeded [in] Size of the data to add.
  98. *
  99. * \return 0 when the buffer is large enough to add the data.
  100. * -1 if no new memory could be allocated.
  101. */
  102. int BufferMakeRoom(char **ppcBuf, unsigned int *punBufSize, unsigned int unBufInUse, unsigned int unSizeNeeded)
  103. {
  104. #ifdef UTIL_DEBUG
  105. LogMsg_P(LOG_DEBUG, PSTR("Have %u,Need %u"), (*punBufSize - unBufInUse), unSizeNeeded);
  106. #endif /* #ifdef UTIL_DEBUG */
  107. if (unSizeNeeded > (*punBufSize - unBufInUse))
  108. {
  109. unsigned int unBlockSize = 256;
  110. char *pNewBuf = NULL;
  111. if (unBlockSize < unSizeNeeded)
  112. {
  113. unBlockSize = unSizeNeeded;
  114. }
  115. pNewBuf = MyMalloc(*punBufSize + unBlockSize);
  116. if (pNewBuf == NULL)
  117. {
  118. return (-1);
  119. }
  120. else
  121. {
  122. *punBufSize += unBlockSize;
  123. #ifdef UTIL_DEBUG
  124. LogMsg_P(LOG_DEBUG, PSTR("MemBlock is %u now"), *punBufSize);
  125. #endif /* #ifdef UTIL_DEBUG */
  126. if (*ppcBuf != NULL)
  127. {
  128. memcpy(pNewBuf, *ppcBuf, unBufInUse);
  129. }
  130. MyFree(*ppcBuf);
  131. *ppcBuf = pNewBuf;
  132. }
  133. }
  134. return (0);
  135. }
  136. /*!
  137. * \brief Add a string to a memory block.
  138. *
  139. * \param ppcBuf [in] Address of a pointer to a memory block.
  140. * \param punBufSize [in,out] The currently allocated size, [out] the new blocksize
  141. * \param unBufInUse [in,out] Currently in use, [out] in use after adding the string
  142. * \param pszString [in] String to add.
  143. *
  144. * \return 0 when the string was successfully added.
  145. * -1 on errors.
  146. */
  147. int BufferAddString(char **ppcBuf, unsigned int *punBufSize, unsigned int *punBufInUse, CONST char *pszString)
  148. {
  149. unsigned int unStringLen = 0;
  150. if (pszString == NULL)
  151. {
  152. return (-1);
  153. }
  154. /*
  155. * Add the line to the response buffer
  156. */
  157. unStringLen = strlen(pszString);
  158. if (unStringLen > 0)
  159. {
  160. unStringLen += 1; /* Correct for \0 */
  161. if (BufferMakeRoom(ppcBuf, punBufSize, *punBufInUse, unStringLen) < 0)
  162. {
  163. return (-1);
  164. }
  165. else
  166. {
  167. /* Only count one \0 (so, in the InUse counter, only count the \0 the very first time) */
  168. if (*punBufInUse != 0)
  169. {
  170. *punBufInUse -= 1;
  171. }
  172. memcpy(&(*ppcBuf)[*punBufInUse], pszString, unStringLen);
  173. *punBufInUse += unStringLen;
  174. }
  175. }
  176. return (0);
  177. }
  178. /*!
  179. * \brief Find a descriptor for a piece of text.
  180. *
  181. * A LookUp Table (LUT) is searched for matching text.
  182. * The row in which the match was found is returned.
  183. * If no match was found, the descriptor of the last entry
  184. * is returned. As a result, the table should always contain
  185. * at least one entry. And that last one should be the
  186. * default/empty or error value, depending on your needs.
  187. *
  188. * \note The compare used is not case sensitive.
  189. * \note If byLen is 0, only the first part of pcText
  190. * needs to match.
  191. * E.g. "foo" in the LUT will match "foo",
  192. * E.g. "foo" in the LUT will match "foobar"
  193. * By passing the length of pcText (not including the
  194. * \0 character), will force an exact match.
  195. * E.g. "foo" in the LUT will match "foo",
  196. * E.g. "foo" in the LUT will not match "foobar",
  197. *
  198. * \param tLookupTable [in] The lookup table.
  199. * \param pcText [in] The text to find the value for
  200. * this does not need to be 0 terminated.
  201. * \param byLen [in] See notes above.
  202. *
  203. * \return The descriptor of the row that matched.
  204. * Or the descriptor of the last row if no match.
  205. */
  206. void *LutSearch(CONST tLut tLookupTable[],
  207. CONST char *pcText,
  208. unsigned char byLen)
  209. {
  210. unsigned char byRow = 0;
  211. for (byRow = 0; byRow < (unsigned char)(-1); byRow++)
  212. {
  213. unsigned char byTagLen = 0;
  214. if (tLookupTable[byRow].pszTag == NULL)
  215. {
  216. break;
  217. }
  218. byTagLen = strlen_P(tLookupTable[byRow].pszTag);
  219. if ((byLen != 0) && (byTagLen != byLen))
  220. {
  221. continue; /* not the same size; keep looking */
  222. }
  223. /* case-insensitive compare */
  224. if (strncasecmp_P(pcText, tLookupTable[byRow].pszTag, byTagLen) == 0)
  225. {
  226. break;
  227. }
  228. }
  229. #ifdef UTIL_DEBUG
  230. LogMsg_P(LOG_DEBUG, PSTR("Match %d"), byRow);
  231. #endif /* #ifdef UTIL_DEBUG */
  232. return (tLookupTable[byRow].pDesc);
  233. }