davide carboni / Mbed 2 deprecated pymite_http_get

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers strobj.c Source File

strobj.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2003, 2006, 2007, 2009 Dean Hall.
00003 #
00004 # This file is part of the PyMite VM.
00005 # The PyMite VM is free software: you can redistribute it and/or modify
00006 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
00007 #
00008 # The PyMite VM is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00011 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
00012 # is seen in the file COPYING in this directory.
00013 */
00014 
00015 
00016 #undef __FILE_ID__
00017 #define __FILE_ID__ 0x12
00018 
00019 
00020 /**
00021  * \file
00022  * \brief String Object Type
00023  *
00024  * String object type opeartions.
00025  */
00026 
00027 #include "pm.h"
00028 
00029 
00030 #if USE_STRING_CACHE
00031 /** String obj cachche: a list of all string objects. */
00032 static pPmString_t pstrcache = C_NULL;
00033 #endif /* USE_STRING_CACHE */
00034 
00035 
00036 /*
00037  * If USE_STRING_CACHE is defined nonzero, the string cache
00038  * will be searched for an existing String object.
00039  * If not found, a new object is created and inserted
00040  * into the cache.
00041  */
00042 PmReturn_t
00043 string_create(PmMemSpace_t memspace, uint8_t const **paddr, int16_t len,
00044               int16_t n, pPmObj_t *r_pstring)
00045 {
00046     PmReturn_t retval = PM_RET_OK;
00047     pPmString_t pstr = C_NULL;
00048     uint8_t *pdst = C_NULL;
00049     uint8_t const *psrc = C_NULL;
00050 
00051 #if USE_STRING_CACHE
00052     pPmString_t pcacheentry = C_NULL;
00053 #endif /* USE_STRING_CACHE */
00054     uint8_t *pchunk;
00055 
00056     /* If loading from an image, get length from the image */
00057     if (len < 0)
00058     {
00059         len = mem_getWord(memspace, paddr);
00060     }
00061 
00062     /* If loading from a C string, get its strlen (first null) */
00063     else if (len == 0)
00064     {
00065         len = sli_strlen((char const *)*paddr);
00066     }
00067 
00068     /* Get space for String obj */
00069     retval = heap_getChunk(sizeof(PmString_t) + len * n, &pchunk);
00070     PM_RETURN_IF_ERROR(retval);
00071     pstr = (pPmString_t)pchunk;
00072 
00073     /* Fill the string obj */
00074     OBJ_SET_TYPE(pstr, OBJ_TYPE_STR);
00075     pstr->length = len * n;
00076 
00077     /* Copy C-string into String obj */
00078     pdst = (uint8_t *)&(pstr->val);
00079     while (--n >= 0)
00080     {
00081         psrc = *paddr;
00082         mem_copy(memspace, &pdst, &psrc, len);
00083     }
00084 
00085     /* Be sure paddr points to one byte past the end of the source string */
00086     *paddr = psrc;
00087 
00088     /* Zero-pad end of string */
00089     for (; pdst < (uint8_t *)pstr + OBJ_GET_SIZE(pstr); pdst++)
00090     {
00091         *pdst = 0;
00092     }
00093 
00094 #if USE_STRING_CACHE
00095     /* Check for twin string in cache */
00096     for (pcacheentry = pstrcache;
00097          pcacheentry != C_NULL; pcacheentry = pcacheentry->next)
00098     {
00099         /* If string already exists */
00100         if (string_compare(pcacheentry, pstr) == C_SAME)
00101         {
00102             /* Free the string */
00103             retval = heap_freeChunk((pPmObj_t)pstr);
00104 
00105             /* Return ptr to old */
00106             *r_pstring = (pPmObj_t)pcacheentry;
00107             return retval;
00108         }
00109     }
00110 
00111     /* Insert string obj into cache */
00112     pstr->next = pstrcache;
00113     pstrcache = pstr;
00114 
00115 #endif /* USE_STRING_CACHE */
00116 
00117     *r_pstring = (pPmObj_t)pstr;
00118     return PM_RET_OK;
00119 }
00120 
00121 
00122 PmReturn_t
00123 string_newFromChar(uint8_t const c, pPmObj_t *r_pstring)
00124 {
00125     PmReturn_t retval;
00126     uint8_t cstr[2];
00127     uint8_t const *pcstr;
00128 
00129     cstr[0] = c;
00130     cstr[1] = '\0';
00131     pcstr = cstr;
00132 
00133     retval = string_new(&pcstr, r_pstring);
00134 
00135     /* If c was a null character, force the length to 1 */
00136     if (c == '\0')
00137     {
00138         ((pPmString_t)*r_pstring)->length = 1;
00139     }
00140 
00141     return retval;
00142 }
00143 
00144 
00145 int8_t
00146 string_compare(pPmString_t pstr1, pPmString_t pstr2)
00147 {
00148     /* Return false if lengths are not equal */
00149     if (pstr1->length != pstr2->length)
00150     {
00151         return C_DIFFER;
00152     }
00153 
00154     /* Compare the strings' contents */
00155     return sli_strncmp((char const *)&(pstr1->val),
00156                        (char const *)&(pstr2->val),
00157                        pstr1->length) == 0 ? C_SAME : C_DIFFER;
00158 }
00159 
00160 
00161 #ifdef HAVE_PRINT
00162 PmReturn_t
00163 string_printFormattedBytes(uint8_t *pb, uint8_t marshall, uint16_t n)
00164 {
00165     uint16_t i;
00166     uint8_t ch;
00167     uint8_t nibble;
00168     PmReturn_t retval = PM_RET_OK;
00169 
00170     if (marshall)
00171     {
00172         retval = plat_putByte('\'');
00173         PM_RETURN_IF_ERROR(retval);
00174     }
00175 
00176     for (i = 0; i < n; i++)
00177     {
00178         ch = pb[i];
00179         if (ch == '\\')
00180         {
00181             /* Output an additional backslash to escape it. */
00182             retval = plat_putByte('\\');
00183             PM_RETURN_IF_ERROR(retval);
00184         }
00185 
00186         /* If the marshalled char is not printable, print its hex escape code */
00187         if (marshall && (ch < (uint8_t)32 || ch >= (uint8_t)128))
00188         {
00189             plat_putByte('\\');
00190             plat_putByte('x');
00191 
00192             nibble = (ch >> (uint8_t)4) + '0';
00193             if (nibble > '9')
00194                 nibble += ('a' - '0' - (uint8_t)10);
00195             plat_putByte(nibble);
00196 
00197             nibble = (ch & (uint8_t)0x0F) + '0';
00198             if (nibble > '9')
00199                 nibble += ('a' - '0' - (uint8_t)10);
00200             plat_putByte(nibble);
00201         }
00202         else
00203         {
00204             /* Simply output character */
00205             retval = plat_putByte(ch);
00206             PM_RETURN_IF_ERROR(retval);
00207         }
00208     }
00209     if (marshall)
00210     {
00211         retval = plat_putByte('\'');
00212     }
00213 
00214     return retval;
00215 }
00216 
00217 
00218 PmReturn_t
00219 string_print(pPmObj_t pstr, uint8_t marshall)
00220 {
00221     PmReturn_t retval = PM_RET_OK;
00222 
00223     C_ASSERT(pstr != C_NULL);
00224 
00225     /* Ensure string obj */
00226     if (OBJ_GET_TYPE(pstr) != OBJ_TYPE_STR)
00227     {
00228         PM_RAISE(retval, PM_RET_EX_TYPE);
00229         return retval;
00230     }
00231 
00232     retval = string_printFormattedBytes(&(((pPmString_t)pstr)->val[0]),
00233                                         marshall,
00234                                         ((pPmString_t)pstr)->length);
00235 
00236     return retval;
00237 }
00238 #endif /* HAVE_PRINT */
00239 
00240 
00241 PmReturn_t
00242 string_cacheInit(void)
00243 {
00244 #if USE_STRING_CACHE
00245     pstrcache = C_NULL;
00246 #endif
00247     return PM_RET_OK;
00248 }
00249 
00250 
00251 PmReturn_t
00252 string_getCache(pPmString_t **r_ppstrcache)
00253 {
00254 #if USE_STRING_CACHE
00255     *r_ppstrcache = &pstrcache;
00256 #else
00257     *r_ppstrcache = C_NULL;
00258 #endif
00259     return PM_RET_OK;
00260 }
00261 
00262 
00263 PmReturn_t
00264 string_concat(pPmString_t pstr1, pPmString_t pstr2, pPmObj_t *r_pstring)
00265 {
00266     PmReturn_t retval = PM_RET_OK;
00267     pPmString_t pstr = C_NULL;
00268     uint8_t *pdst = C_NULL;
00269     uint8_t const *psrc = C_NULL;
00270 #if USE_STRING_CACHE
00271     pPmString_t pcacheentry = C_NULL;
00272 #endif /* USE_STRING_CACHE */
00273     uint8_t *pchunk;
00274     uint16_t len;
00275 
00276     /* Create the String obj */
00277     len = pstr1->length + pstr2->length;
00278     retval = heap_getChunk(sizeof(PmString_t) + len, &pchunk);
00279     PM_RETURN_IF_ERROR(retval);
00280     pstr = (pPmString_t)pchunk;
00281     OBJ_SET_TYPE(pstr, OBJ_TYPE_STR);
00282     pstr->length = len;
00283 
00284     /* Concatenate C-strings into String obj and apply null terminator */
00285     pdst = (uint8_t *)&(pstr->val);
00286     psrc = (uint8_t const *)&(pstr1->val);
00287     mem_copy(MEMSPACE_RAM, &pdst, &psrc, pstr1->length);
00288     psrc = (uint8_t const *)&(pstr2->val);
00289     mem_copy(MEMSPACE_RAM, &pdst, &psrc, pstr2->length);
00290     *pdst = '\0';
00291 
00292 #if USE_STRING_CACHE
00293     /* Check for twin string in cache */
00294     for (pcacheentry = pstrcache;
00295          pcacheentry != C_NULL; pcacheentry = pcacheentry->next)
00296     {
00297         /* If string already exists */
00298         if (string_compare(pcacheentry, pstr) == C_SAME)
00299         {
00300             /* Free the string */
00301             retval = heap_freeChunk((pPmObj_t)pstr);
00302 
00303             /* Return ptr to old */
00304             *r_pstring = (pPmObj_t)pcacheentry;
00305             return retval;
00306         }
00307     }
00308 
00309     /* Insert string obj into cache */
00310     pstr->next = pstrcache;
00311     pstrcache = pstr;
00312 #endif /* USE_STRING_CACHE */
00313 
00314     *r_pstring = (pPmObj_t)pstr;
00315     return PM_RET_OK;
00316 }
00317 
00318 
00319 #ifdef HAVE_STRING_FORMAT
00320 
00321 #define SIZEOF_FMTDBUF 42
00322 #define SIZEOF_SMALLFMT 8
00323 
00324 PmReturn_t
00325 string_format(pPmString_t pstr, pPmObj_t parg, pPmObj_t *r_pstring)
00326 {
00327     PmReturn_t retval;
00328     uint16_t strsize = 0;
00329     uint16_t strindex;
00330     uint8_t *fmtcstr;
00331     uint8_t smallfmtcstr[SIZEOF_SMALLFMT];
00332     uint8_t fmtdbuf[SIZEOF_FMTDBUF];
00333     uint8_t i;
00334     uint8_t j;
00335     uint8_t argtupleindex = 0;
00336     pPmObj_t pobj;
00337     int snprintretval;
00338     uint8_t expectedargcount = 0;
00339     pPmString_t pnewstr;
00340     uint8_t *pchunk;
00341 #if USE_STRING_CACHE
00342     pPmString_t pcacheentry = C_NULL;
00343 #endif /* USE_STRING_CACHE */
00344 
00345     /* Get the first arg */
00346     pobj = parg;
00347 
00348     /* Calculate the size of the resulting string */
00349     fmtcstr = pstr->val;
00350     for (i = 0; i < pstr->length; i++)
00351     {
00352         /* Count non-format chars */
00353         if (fmtcstr[i] != '%') { strsize++; continue; }
00354 
00355         /* If double percents, count one percent */
00356         if (fmtcstr[++i] == '%') { strsize++; continue; }
00357 
00358         /* Get arg from the tuple */
00359         if (OBJ_GET_TYPE(parg) == OBJ_TYPE_TUP)
00360         {
00361             pobj = ((pPmTuple_t)parg)->val[argtupleindex++];
00362         }
00363 
00364         snprintretval = -1;
00365 
00366         /* Format one arg to get its length */
00367         smallfmtcstr[0] = '%';
00368         for(j = 1; (i < pstr->length) && (j < SIZEOF_SMALLFMT); i++)
00369         {
00370             smallfmtcstr[j] = fmtcstr[i];
00371             j++;
00372 
00373             if (fmtcstr[i] == 'd')
00374             {
00375                 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT)
00376                 {
00377                     PM_RAISE(retval, PM_RET_EX_TYPE);
00378                     return retval;
00379                 }
00380                 smallfmtcstr[j] = '\0';
00381                 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00382                     (char *)smallfmtcstr, ((pPmInt_t)pobj)->val);
00383                 break;
00384             }
00385 
00386 #ifdef HAVE_FLOAT
00387             else if (fmtcstr[i] == 'f')
00388             {
00389                 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_FLT)
00390                 {
00391                     PM_RAISE(retval, PM_RET_EX_TYPE);
00392                     return retval;
00393                 }
00394                 smallfmtcstr[j] = '\0';
00395                 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00396                     (char *)smallfmtcstr, ((pPmFloat_t)pobj)->val);
00397                 break;
00398             }
00399 #endif /* HAVE_FLOAT */
00400 
00401             else if (fmtcstr[i] == 's')
00402             {
00403                 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR)
00404                 {
00405                     PM_RAISE(retval, PM_RET_EX_TYPE);
00406                     return retval;
00407                 }
00408                 smallfmtcstr[j] = '\0';
00409                 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00410                     (char *)smallfmtcstr, ((pPmString_t)pobj)->val);
00411                 break;
00412             }
00413         }
00414 
00415         /* Raise ValueError if the format string was bad */
00416         if (snprintretval < 0)
00417         {
00418             PM_RAISE(retval, PM_RET_EX_VAL);
00419             return retval;
00420         }
00421 
00422         expectedargcount++;
00423         strsize += snprintretval;
00424     }
00425 
00426     /* TypeError wrong number args */
00427     if (((OBJ_GET_TYPE(parg) != OBJ_TYPE_TUP) && (expectedargcount != 1))
00428         || ((OBJ_GET_TYPE(parg) == OBJ_TYPE_TUP)
00429             && (expectedargcount != ((pPmTuple_t)parg)->length)))
00430     {
00431         PM_RAISE(retval, PM_RET_EX_TYPE);
00432         return retval;
00433     }
00434 
00435     /* Allocate and initialize String obj */
00436     retval = heap_getChunk(sizeof(PmString_t) + strsize, &pchunk);
00437     PM_RETURN_IF_ERROR(retval);
00438     pnewstr = (pPmString_t)pchunk;
00439     OBJ_SET_TYPE(pnewstr, OBJ_TYPE_STR);
00440     pnewstr->length = strsize;
00441 
00442 
00443     /* Fill contents of String obj */
00444     strindex = 0;
00445     argtupleindex = 0;
00446     pobj = parg;
00447 
00448     for (i = 0; i < pstr->length; i++)
00449     {
00450         /* Copy non-format chars */
00451         if (fmtcstr[i] != '%')
00452         {
00453             pnewstr->val[strindex++] = fmtcstr[i];
00454             continue;
00455         }
00456 
00457         /* If double percents, copy one percent */
00458         if (fmtcstr[++i] == '%')
00459         {
00460             pnewstr->val[strindex++] = '%';
00461             continue;
00462         }
00463 
00464         /* Get arg from the tuple */
00465         if (OBJ_GET_TYPE(parg) == OBJ_TYPE_TUP)
00466         {
00467             pobj = ((pPmTuple_t)parg)->val[argtupleindex++];
00468         }
00469 
00470         snprintretval = -1;
00471 
00472         /* Format one arg to get its length */
00473         smallfmtcstr[0] = '%';
00474         for(j = 1; (i < pstr->length) && (j < SIZEOF_SMALLFMT); i++)
00475         {
00476             smallfmtcstr[j] = fmtcstr[i];
00477             j++;
00478 
00479             if (fmtcstr[i] == 'd')
00480             {
00481                 smallfmtcstr[j] = '\0';
00482                 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00483                     (char *)smallfmtcstr, ((pPmInt_t)pobj)->val);
00484                 break;
00485             }
00486 
00487 #ifdef HAVE_FLOAT
00488             else if (fmtcstr[i] == 'f')
00489             {
00490                 smallfmtcstr[j] = '\0';
00491                 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00492                     (char *)smallfmtcstr, ((pPmFloat_t)pobj)->val);
00493                 break;
00494             }
00495 #endif /* HAVE_FLOAT */
00496 
00497             else if (fmtcstr[i] == 's')
00498             {
00499                 smallfmtcstr[j] = '\0';
00500                 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00501                     (char *)smallfmtcstr, ((pPmString_t)pobj)->val);
00502                 break;
00503             }
00504         }
00505 
00506         /* Copy formatted C string into new string object */
00507         for (j = 0; j < snprintretval; j++)
00508         {
00509             pnewstr->val[strindex++] = fmtdbuf[j];
00510         }
00511     }
00512     pnewstr->val[strindex] = '\0';
00513 
00514 #if USE_STRING_CACHE
00515     /* Check for twin string in cache */
00516     for (pcacheentry = pstrcache;
00517          pcacheentry != C_NULL; pcacheentry = pcacheentry->next)
00518     {
00519         /* If string already exists */
00520         if (string_compare(pcacheentry, pnewstr) == C_SAME)
00521         {
00522             /* Free the string */
00523             retval = heap_freeChunk((pPmObj_t)pnewstr);
00524 
00525             /* Return ptr to old */
00526             *r_pstring = (pPmObj_t)pcacheentry;
00527             return retval;
00528         }
00529     }
00530 
00531     /* Insert string obj into cache */
00532     pnewstr->next = pstrcache;
00533     pstrcache = pnewstr;
00534 
00535 #endif /* USE_STRING_CACHE */
00536 
00537     *r_pstring = (pPmObj_t)pnewstr;
00538     return PM_RET_OK;
00539 }
00540 #endif /* HAVE_STRING_FORMAT */