static const char * _hb_jsonDecode( const char * szSource, PHB_ITEM pValue ) { if( *szSource == '\"' ) { char * szDest, * szHead; HB_SIZE nAlloc = 16; szHead = szDest = ( char * ) hb_xgrab( nAlloc ); szSource++; while( *szSource != '\"' ) { if( szHead + 6 >= szDest + nAlloc ) { HB_SIZE nLen = szHead - szDest; nAlloc += nAlloc << 1; szDest = ( char * ) hb_xrealloc( szDest, nAlloc ); szHead = szDest + nLen; } if( *szSource == '\\' ) { szSource++; switch( *szSource ) { case '\"': *szHead++ = '\"'; break; case '\\': *szHead++ = '\\'; break; case '/': *szHead++ = '/'; break; case 'b': *szHead++ = '\b'; break; case 'f': *szHead++ = '\f'; break; case 'n': *szHead++ = '\n'; break; case 'r': *szHead++ = '\r'; break; case 't': *szHead++ = '\t'; break; case 'u': { HB_WCHAR wc = 0; int i; for( i = 0; i < 4; i++ ) { char c = *++szSource; wc <<= 4; if( c >= '0' && c <= '9' ) wc += c - '0'; else if( c >= 'A' && c <= 'F' ) wc += c - 'A' + 10; else if( c >= 'a' && c <= 'f' ) wc += c - 'a' + 10; else { hb_xfree( szDest ); return NULL; } } szHead += hb_cdpU16ToStr( hb_vmCDP(), HB_CDP_ENDIAN_NATIVE, &wc, 1, szHead, szDest + nAlloc - szHead ); break; } default: hb_xfree( szDest ); return NULL; } szSource++; } else if( *( const unsigned char * ) szSource >= ' ' ) *szHead++ = *szSource++; else { hb_xfree( szDest ); return NULL; } } hb_itemPutCL( pValue, szDest, szHead - szDest ); hb_xfree( szDest ); return szSource + 1; } else if( *szSource == '-' || ( *szSource >= '0' && *szSource <= '9' ) ) { /* NOTE: this function is much less strict to number format than JSON syntax definition. This is allowed behaviour [Mindaugas] */ HB_MAXINT nValue = 0; double dblValue = 0; HB_BOOL fNeg, fDbl = HB_FALSE; int iDec = 0; fNeg = *szSource == '-'; if( fNeg ) szSource++; while( *szSource >= '0' && *szSource <= '9' ) { nValue = nValue * 10 + *szSource - '0'; szSource++; } if( *szSource == '.' ) { double mult = 1; dblValue = ( double ) nValue; fDbl = HB_TRUE; szSource++; while( *szSource >= '0' && *szSource <= '9' ) { mult /= 10; dblValue += ( ( double ) ( *szSource - '0' ) ) * mult; szSource++; iDec++; } } if( *szSource == 'e' || *szSource == 'E' ) { HB_BOOL fNegExp; int iExp = 0; szSource++; fNegExp = *szSource == '-'; if( fNegExp ) szSource++; while( *szSource >= '0' && *szSource <= '9' ) { iExp = iExp * 10 + *szSource - '0'; szSource++; } if( ! fDbl ) { dblValue = ( double ) nValue; fDbl = HB_TRUE; } if( fNegExp ) iDec += iExp; dblValue = hb_numExpConv( dblValue, fNegExp ? iExp : -iExp ); } if( fDbl ) hb_itemPutNDDec( pValue, hb_numRound( fNeg ? -dblValue : dblValue, iDec ), iDec ); else hb_itemPutNInt( pValue, fNeg ? -nValue : nValue ); return szSource; } else if( ! strncmp( szSource, "null", 4 ) ) { hb_itemClear( pValue ); return szSource + 4; } else if( ! strncmp( szSource, "true", 4 ) ) { hb_itemPutL( pValue, HB_TRUE ); return szSource + 4; } else if( ! strncmp( szSource, "false", 5 ) ) { hb_itemPutL( pValue, HB_FALSE ); return szSource + 5; } else if( *szSource == '[' ) { hb_arrayNew( pValue, 0 ); szSource = _skipws( szSource + 1 ); if( *szSource != ']' ) { PHB_ITEM pItem = hb_itemNew( NULL ); for( ;; ) { szSource = _hb_jsonDecode( szSource, pItem ); if( ! szSource ) { hb_itemRelease( pItem ); return NULL; } hb_arrayAddForward( pValue, pItem ); szSource = _skipws( szSource ); if( *szSource == ',' ) { szSource = _skipws( szSource + 1 ); continue; } else if( *szSource == ']' ) break; else { hb_itemRelease( pItem ); return NULL; } } hb_itemRelease( pItem ); } return szSource + 1; } else if( *szSource == '{' ) { hb_hashNew( pValue ); szSource = _skipws( szSource + 1 ); if( *szSource != '}' ) { PHB_ITEM pItemKey = hb_itemNew( NULL ); PHB_ITEM pItemValue = hb_itemNew( NULL ); for( ;; ) { /* Do we need to check if key does not exist yet? */ if( ( szSource = _hb_jsonDecode( szSource, pItemKey ) ) == NULL || ! HB_IS_STRING( pItemKey ) || * ( szSource = _skipws( szSource ) ) != ':' || ( szSource = _hb_jsonDecode( _skipws( szSource + 1 ), pItemValue ) ) == NULL) { hb_itemRelease( pItemKey ); hb_itemRelease( pItemValue ); return NULL; } hb_hashAdd( pValue, pItemKey, pItemValue ); szSource = _skipws( szSource ); if( *szSource == ',' ) { szSource = _skipws( szSource + 1 ); continue; } else if( *szSource == '}' ) break; else { hb_itemRelease( pItemKey ); hb_itemRelease( pItemValue ); return NULL; } } hb_itemRelease( pItemKey ); hb_itemRelease( pItemValue ); } return szSource + 1; } return NULL; }
static long hb_i18n_pluralindex( int iForm, PHB_ITEM pNum ) { double n = hb_numRound( hb_itemGetND( pNum ), 10 ), n10, n100; switch( iForm ) { case HB_I18N_PLURAL_PL: n10 = fmod( n, 10.0 ); n100 = fmod( n, 100.0 ); return n == 1 ? 1 : ( n10 >= 2 && n10 <= 4 && ( n100 < 10 || n100 >= 20 ) ? 2 : 3 ); case HB_I18N_PLURAL_RO: n100 = fmod( n, 100.0 ); return n == 1 ? 1 : ( n == 0 || ( n100 > 0 && n100 < 20 ) ) ? 2 : 3; case HB_I18N_PLURAL_HR: case HB_I18N_PLURAL_SR: case HB_I18N_PLURAL_RU: case HB_I18N_PLURAL_UK: n10 = fmod( n, 10.0 ); n100 = fmod( n, 100.0 ); return n10 == 1 && n100 != 11 ? 1 : n10 >= 2 && n10 <= 4 && ( n100 < 10 || n100 >= 20 ) ? 2 : 3; case HB_I18N_PLURAL_CS: case HB_I18N_PLURAL_SK: return n == 1 ? 1 : ( ( n >= 2 && n <= 4 ) ? 2 : 3 ); case HB_I18N_PLURAL_SL: n100 = fmod( n, 100.0 ); return n100 == 1 ? 1 : ( n100 == 2 ? 1 : ( n100 == 3 || n100 == 4 ? 3 : 4 ) ); case HB_I18N_PLURAL_LT: n10 = fmod( n, 10.0 ); n100 = fmod( n, 100.0 ); return n10 == 1 && n100 != 11 ? 1 : ( n10 != 0 && ( n100 < 10 || n100 >= 20 ) ? 2 : 3 ); case HB_I18N_PLURAL_LV: n10 = fmod( n, 10.0 ); n100 = fmod( n, 100.0 ); return ( n10 == 1 && n100 != 11 ) ? 1 : ( n != 0 ? 2 : 3 ); case HB_I18N_PLURAL_GA: return n == 1 ? 1 : ( n == 2 ? 2 : 3 ); case HB_I18N_PLURAL_JA: case HB_I18N_PLURAL_KO: case HB_I18N_PLURAL_VI: case HB_I18N_PLURAL_TR: return 1; case HB_I18N_PLURAL_FR: case HB_I18N_PLURAL_PT_BR: return n <= 1 ? 1 : 2; case HB_I18N_PLURAL_EN: case HB_I18N_PLURAL_HU: default: return n == 1 ? 1 : 2; } }