00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #undef __FILE_ID__
00017 #define __FILE_ID__ 0x12
00018
00019
00027 #include "pm.h"
00028
00029
00030 #if USE_STRING_CACHE
00031
00032 static pPmString_t pstrcache = C_NULL;
00033 #endif
00034
00035
00036
00037
00038
00039
00040
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
00054 uint8_t *pchunk;
00055
00056
00057 if (len < 0)
00058 {
00059 len = mem_getWord(memspace, paddr);
00060 }
00061
00062
00063 else if (len == 0)
00064 {
00065 len = sli_strlen((char const *)*paddr);
00066 }
00067
00068
00069 retval = heap_getChunk(sizeof(PmString_t) + len * n, &pchunk);
00070 PM_RETURN_IF_ERROR(retval);
00071 pstr = (pPmString_t)pchunk;
00072
00073
00074 OBJ_SET_TYPE(pstr, OBJ_TYPE_STR);
00075 pstr->length = len * n;
00076
00077
00078 pdst = (uint8_t *)&(pstr->val);
00079 while (--n >= 0)
00080 {
00081 psrc = *paddr;
00082 mem_copy(memspace, &pdst, &psrc, len);
00083 }
00084
00085
00086 *paddr = psrc;
00087
00088
00089 for (; pdst < (uint8_t *)pstr + OBJ_GET_SIZE(pstr); pdst++)
00090 {
00091 *pdst = 0;
00092 }
00093
00094 #if USE_STRING_CACHE
00095
00096 for (pcacheentry = pstrcache;
00097 pcacheentry != C_NULL; pcacheentry = pcacheentry->next)
00098 {
00099
00100 if (string_compare(pcacheentry, pstr) == C_SAME)
00101 {
00102
00103 retval = heap_freeChunk((pPmObj_t)pstr);
00104
00105
00106 *r_pstring = (pPmObj_t)pcacheentry;
00107 return retval;
00108 }
00109 }
00110
00111
00112 pstr->next = pstrcache;
00113 pstrcache = pstr;
00114
00115 #endif
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
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
00149 if (pstr1->length != pstr2->length)
00150 {
00151 return C_DIFFER;
00152 }
00153
00154
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 is_escaped, 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 (is_escaped)
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 (is_escaped && (ch == '\\'))
00180 {
00181
00182 retval = plat_putByte('\\');
00183 PM_RETURN_IF_ERROR(retval);
00184 }
00185
00186
00187 if (is_escaped
00188 && ((ch < (uint8_t)32) || (ch >= (uint8_t)128) || (ch == '\'')))
00189 {
00190 plat_putByte('\\');
00191 plat_putByte('x');
00192
00193 nibble = (ch >> (uint8_t)4) + '0';
00194 if (nibble > '9')
00195 nibble += ('a' - '0' - (uint8_t)10);
00196 plat_putByte(nibble);
00197
00198 nibble = (ch & (uint8_t)0x0F) + '0';
00199 if (nibble > '9')
00200 nibble += ('a' - '0' - (uint8_t)10);
00201 plat_putByte(nibble);
00202 }
00203 else
00204 {
00205
00206 retval = plat_putByte(ch);
00207 PM_RETURN_IF_ERROR(retval);
00208 }
00209 }
00210 if (is_escaped)
00211 {
00212 retval = plat_putByte('\'');
00213 }
00214
00215 return retval;
00216 }
00217
00218
00219 PmReturn_t
00220 string_print(pPmObj_t pstr, uint8_t is_escaped)
00221 {
00222 PmReturn_t retval = PM_RET_OK;
00223
00224 C_ASSERT(pstr != C_NULL);
00225
00226
00227 if (OBJ_GET_TYPE(pstr) != OBJ_TYPE_STR)
00228 {
00229 PM_RAISE(retval, PM_RET_EX_TYPE);
00230 return retval;
00231 }
00232
00233 retval = string_printFormattedBytes(&(((pPmString_t)pstr)->val[0]),
00234 is_escaped,
00235 ((pPmString_t)pstr)->length);
00236
00237 return retval;
00238 }
00239 #endif
00240
00241
00242 PmReturn_t
00243 string_cacheInit(void)
00244 {
00245 #if USE_STRING_CACHE
00246 pstrcache = C_NULL;
00247 #endif
00248 return PM_RET_OK;
00249 }
00250
00251
00252 PmReturn_t
00253 string_getCache(pPmString_t **r_ppstrcache)
00254 {
00255 #if USE_STRING_CACHE
00256 *r_ppstrcache = &pstrcache;
00257 #else
00258 *r_ppstrcache = C_NULL;
00259 #endif
00260 return PM_RET_OK;
00261 }
00262
00263
00264 PmReturn_t
00265 string_concat(pPmString_t pstr1, pPmString_t pstr2, pPmObj_t *r_pstring)
00266 {
00267 PmReturn_t retval = PM_RET_OK;
00268 pPmString_t pstr = C_NULL;
00269 uint8_t *pdst = C_NULL;
00270 uint8_t const *psrc = C_NULL;
00271 #if USE_STRING_CACHE
00272 pPmString_t pcacheentry = C_NULL;
00273 #endif
00274 uint8_t *pchunk;
00275 uint16_t len;
00276
00277
00278 len = pstr1->length + pstr2->length;
00279 retval = heap_getChunk(sizeof(PmString_t) + len, &pchunk);
00280 PM_RETURN_IF_ERROR(retval);
00281 pstr = (pPmString_t)pchunk;
00282 OBJ_SET_TYPE(pstr, OBJ_TYPE_STR);
00283 pstr->length = len;
00284
00285
00286 pdst = (uint8_t *)&(pstr->val);
00287 psrc = (uint8_t const *)&(pstr1->val);
00288 mem_copy(MEMSPACE_RAM, &pdst, &psrc, pstr1->length);
00289 psrc = (uint8_t const *)&(pstr2->val);
00290 mem_copy(MEMSPACE_RAM, &pdst, &psrc, pstr2->length);
00291 *pdst = '\0';
00292
00293 #if USE_STRING_CACHE
00294
00295 for (pcacheentry = pstrcache;
00296 pcacheentry != C_NULL; pcacheentry = pcacheentry->next)
00297 {
00298
00299 if (string_compare(pcacheentry, pstr) == C_SAME)
00300 {
00301
00302 retval = heap_freeChunk((pPmObj_t)pstr);
00303
00304
00305 *r_pstring = (pPmObj_t)pcacheentry;
00306 return retval;
00307 }
00308 }
00309
00310
00311 pstr->next = pstrcache;
00312 pstrcache = pstr;
00313 #endif
00314
00315 *r_pstring = (pPmObj_t)pstr;
00316 return PM_RET_OK;
00317 }
00318
00319
00320 #ifdef HAVE_STRING_FORMAT
00321
00322 #define SIZEOF_FMTDBUF 42
00323 #define SIZEOF_SMALLFMT 8
00324
00325 PmReturn_t
00326 string_format(pPmString_t pstr, pPmObj_t parg, pPmObj_t *r_pstring)
00327 {
00328 PmReturn_t retval;
00329 uint16_t strsize = 0;
00330 uint16_t strindex;
00331 uint8_t *fmtcstr;
00332 uint8_t smallfmtcstr[SIZEOF_SMALLFMT];
00333 uint8_t fmtdbuf[SIZEOF_FMTDBUF];
00334 uint8_t i;
00335 uint8_t j;
00336 uint8_t argtupleindex = 0;
00337 pPmObj_t pobj;
00338 int snprintretval;
00339 uint8_t expectedargcount = 0;
00340 pPmString_t pnewstr;
00341 uint8_t *pchunk;
00342 #if USE_STRING_CACHE
00343 pPmString_t pcacheentry = C_NULL;
00344 #endif
00345
00346
00347 pobj = parg;
00348
00349
00350 fmtcstr = pstr->val;
00351 for (i = 0; i < pstr->length; i++)
00352 {
00353
00354 if (fmtcstr[i] != '%') { strsize++; continue; }
00355
00356
00357 if (fmtcstr[++i] == '%') { strsize++; continue; }
00358
00359
00360 if (OBJ_GET_TYPE(parg) == OBJ_TYPE_TUP)
00361 {
00362 pobj = ((pPmTuple_t)parg)->val[argtupleindex++];
00363 }
00364
00365 snprintretval = -1;
00366
00367
00368 smallfmtcstr[0] = '%';
00369 for(j = 1; (i < pstr->length) && (j < SIZEOF_SMALLFMT); i++)
00370 {
00371 smallfmtcstr[j] = fmtcstr[i];
00372 j++;
00373
00374 if ((fmtcstr[i] == 'd')
00375 || (fmtcstr[i] == 'x')
00376 || (fmtcstr[i] == 'X'))
00377 {
00378 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT)
00379 {
00380 PM_RAISE(retval, PM_RET_EX_TYPE);
00381 return retval;
00382 }
00383 smallfmtcstr[j] = '\0';
00384 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00385 (char *)smallfmtcstr, ((pPmInt_t)pobj)->val);
00386 break;
00387 }
00388
00389 #ifdef HAVE_FLOAT
00390 else if (fmtcstr[i] == 'f')
00391 {
00392 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_FLT)
00393 {
00394 PM_RAISE(retval, PM_RET_EX_TYPE);
00395 return retval;
00396 }
00397 smallfmtcstr[j] = '\0';
00398 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00399 (char *)smallfmtcstr, ((pPmFloat_t)pobj)->val);
00400 break;
00401 }
00402 #endif
00403
00404 else if (fmtcstr[i] == 's')
00405 {
00406 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR)
00407 {
00408 PM_RAISE(retval, PM_RET_EX_TYPE);
00409 return retval;
00410 }
00411 smallfmtcstr[j] = '\0';
00412 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00413 (char *)smallfmtcstr, ((pPmString_t)pobj)->val);
00414 break;
00415 }
00416 }
00417
00418
00419 if (snprintretval < 0)
00420 {
00421 PM_RAISE(retval, PM_RET_EX_VAL);
00422 return retval;
00423 }
00424
00425 expectedargcount++;
00426 strsize += snprintretval;
00427 }
00428
00429
00430 if (((OBJ_GET_TYPE(parg) != OBJ_TYPE_TUP) && (expectedargcount != 1))
00431 || ((OBJ_GET_TYPE(parg) == OBJ_TYPE_TUP)
00432 && (expectedargcount != ((pPmTuple_t)parg)->length)))
00433 {
00434 PM_RAISE(retval, PM_RET_EX_TYPE);
00435 return retval;
00436 }
00437
00438
00439 retval = heap_getChunk(sizeof(PmString_t) + strsize, &pchunk);
00440 PM_RETURN_IF_ERROR(retval);
00441 pnewstr = (pPmString_t)pchunk;
00442 OBJ_SET_TYPE(pnewstr, OBJ_TYPE_STR);
00443 pnewstr->length = strsize;
00444
00445
00446
00447 strindex = 0;
00448 argtupleindex = 0;
00449 pobj = parg;
00450
00451 for (i = 0; i < pstr->length; i++)
00452 {
00453
00454 if (fmtcstr[i] != '%')
00455 {
00456 pnewstr->val[strindex++] = fmtcstr[i];
00457 continue;
00458 }
00459
00460
00461 if (fmtcstr[++i] == '%')
00462 {
00463 pnewstr->val[strindex++] = '%';
00464 continue;
00465 }
00466
00467
00468 if (OBJ_GET_TYPE(parg) == OBJ_TYPE_TUP)
00469 {
00470 pobj = ((pPmTuple_t)parg)->val[argtupleindex++];
00471 }
00472
00473 snprintretval = -1;
00474
00475
00476 smallfmtcstr[0] = '%';
00477 for(j = 1; (i < pstr->length) && (j < SIZEOF_SMALLFMT); i++)
00478 {
00479 smallfmtcstr[j] = fmtcstr[i];
00480 j++;
00481
00482 if ((fmtcstr[i] == 'd')
00483 || (fmtcstr[i] == 'x')
00484 || (fmtcstr[i] == 'X'))
00485 {
00486 smallfmtcstr[j] = '\0';
00487 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00488 (char *)smallfmtcstr, ((pPmInt_t)pobj)->val);
00489 break;
00490 }
00491
00492 #ifdef HAVE_FLOAT
00493 else if (fmtcstr[i] == 'f')
00494 {
00495 smallfmtcstr[j] = '\0';
00496 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00497 (char *)smallfmtcstr, ((pPmFloat_t)pobj)->val);
00498 break;
00499 }
00500 #endif
00501
00502 else if (fmtcstr[i] == 's')
00503 {
00504 smallfmtcstr[j] = '\0';
00505 snprintretval = snprintf((char *)fmtdbuf, SIZEOF_FMTDBUF,
00506 (char *)smallfmtcstr, ((pPmString_t)pobj)->val);
00507 break;
00508 }
00509 }
00510
00511
00512 for (j = 0; j < snprintretval; j++)
00513 {
00514 pnewstr->val[strindex++] = fmtdbuf[j];
00515 }
00516 }
00517 pnewstr->val[strindex] = '\0';
00518
00519 #if USE_STRING_CACHE
00520
00521 for (pcacheentry = pstrcache;
00522 pcacheentry != C_NULL; pcacheentry = pcacheentry->next)
00523 {
00524
00525 if (string_compare(pcacheentry, pnewstr) == C_SAME)
00526 {
00527
00528 retval = heap_freeChunk((pPmObj_t)pnewstr);
00529
00530
00531 *r_pstring = (pPmObj_t)pcacheentry;
00532 return retval;
00533 }
00534 }
00535
00536
00537 pnewstr->next = pstrcache;
00538 pstrcache = pnewstr;
00539
00540 #endif
00541
00542 *r_pstring = (pPmObj_t)pnewstr;
00543 return PM_RET_OK;
00544 }
00545 #endif