@@ -159,14 +159,13 @@ static void detectAndroid(FFCPUResult* cpu)
159159#if  __arm__  ||  __aarch64__ 
160160#include  "cpu_arm.h" 
161161
162- static  void  detectArmName (FILE *  cpuinfo , FFCPUResult *  cpu , uint32_t  implId )
162+ static  void  detectArmName (FFstrbuf *  cpuinfo , FFCPUResult *  cpu , uint32_t  implId )
163163{
164-     FF_AUTO_FREE  char *  line  =  NULL ;
165-     rewind (cpuinfo );
164+     char *  line  =  NULL ;
166165    size_t  len  =  0 ;
167166    uint32_t  lastPartId  =  UINT32_MAX ;
168167    uint32_t  num  =  0 ;
169-     while (getline (& line , & len , cpuinfo )  !=   -1 )
168+     while (ffStrbufGetline (& line , & len , cpuinfo ))
170169    {
171170        if  (!ffStrStartsWith (line , "CPU part\t: " )) continue ;
172171        uint32_t  partId  =  (uint32_t ) strtoul (line  +  strlen ("CPU part\t: " ), NULL , 16 );
@@ -220,19 +219,18 @@ static void detectArmName(FILE* cpuinfo, FFCPUResult* cpu, uint32_t implId)
220219#endif 
221220
222221static  const  char *  parseCpuInfo (
223-     FF_MAYBE_UNUSED  FILE *  cpuinfo ,
224-     FF_MAYBE_UNUSED  FFCPUResult *  cpu ,
225-     FF_MAYBE_UNUSED  FFstrbuf *  cpuPhysicalId ,
222+     FFstrbuf *  cpuinfo ,
223+     FFCPUResult *  cpu ,
226224    FF_MAYBE_UNUSED  FFstrbuf *  physicalCoresBuffer ,
227225    FF_MAYBE_UNUSED  FFstrbuf *  cpuMHz ,
228226    FF_MAYBE_UNUSED  FFstrbuf *  cpuIsa ,
229227    FF_MAYBE_UNUSED  FFstrbuf *  cpuUarch ,
230228    FF_MAYBE_UNUSED  FFstrbuf *  cpuImplementer )
231229{
232-     FF_AUTO_FREE   char *  line  =  NULL ;
230+     char *  line  =  NULL ;
233231    size_t  len  =  0 ;
234232
235-     while (getline (& line , & len , cpuinfo )  !=   -1 )
233+     while (ffStrbufGetline (& line , & len , cpuinfo ))
236234    {
237235        //Stop after reasonable information is acquired 
238236        if ((* line  ==  '\0'  ||  * line  ==  '\n' )
@@ -248,9 +246,6 @@ static const char* parseCpuInfo(
248246            #if  !(__arm__  ||  __aarch64__ )
249247            (cpu -> name .length  ==  0  &&  ffParsePropLine (line , "model name :" , & cpu -> name )) || 
250248            (cpu -> vendor .length  ==  0  &&  ffParsePropLine (line , "vendor_id :" , & cpu -> vendor )) || 
251-             //Is it cheaper to just parse every physical id or to check if it's already set to the parsed value? 
252-             (cpuPhysicalId -> length  ==  0  &&  ffParsePropLine (line , "physical id:" , cpuPhysicalId )) || 
253-             (cpuPhysicalId -> length  >  0  &&  ffParsePropLine (line , "physical id:" , cpuPhysicalId )) || 
254249            (physicalCoresBuffer -> length  ==  0  &&  ffParsePropLine (line , "cpu cores :" , physicalCoresBuffer )) || 
255250            (cpuMHz -> length  ==  0  &&  ffParsePropLine (line , "cpu MHz :" , cpuMHz )) || 
256251            #endif 
@@ -469,28 +464,45 @@ FF_MAYBE_UNUSED static void detectArmSoc(FFCPUResult* cpu)
469464    }
470465}
471466
467+ FF_MAYBE_UNUSED  static  uint16_t  getCPUCount (FFstrbuf *  cpuinfo )
468+ {
469+     const  char *  p  =  cpuinfo -> chars ;
470+     uint64_t  bits  =  0 ;
471+ 
472+     while  ((p  =  memmem (p , cpuinfo -> length  -  (uint32_t ) (p  -  cpuinfo -> chars ), "\nphysical id\t:" , strlen ("\nphysical id\t:" ))))
473+     {
474+         if  (!p ) break ;
475+         p  +=  strlen ("\nphysical id\t:" );
476+         char *  pend ;
477+         uint32_t  id  =  (uint32_t ) strtoul (p , & pend , 10 );
478+         p  =  pend ;
479+         bits  |= 1  << id ;
480+     }
481+ 
482+     return  (uint16_t ) __builtin_popcountll (bits );
483+ }
484+ 
472485const  char *  ffDetectCPUImpl (const  FFCPUOptions *  options , FFCPUResult *  cpu )
473486{
474-     FF_AUTO_CLOSE_FILE   FILE *   cpuinfo  =  fopen ( "/proc/cpuinfo" ,  "r" );
475-     if ( cpuinfo   ==  NULL )
476-         return  "fopen (\"/proc/cpuinfo\", \"r \") failed" ;
487+     FF_STRBUF_AUTO_DESTROY   cpuinfo  =  ffStrbufCreateA ( PROC_FILE_BUFFSIZ );
488+     if  (! ffReadFileBuffer ( "/proc/ cpuinfo" ,  & cpuinfo )  ||   cpuinfo . length   ==  0 )
489+         return  "ffReadFileBuffer (\"/proc/cpuinfo\") failed" ;
477490
478491    cpu -> temperature  =  options -> temp  ? detectCPUTemp () : FF_CPU_TEMP_UNSET ;
479492
480-     FF_STRBUF_AUTO_DESTROY  cpuPhysicalId =  ffStrbufCreate ();
481493    FF_STRBUF_AUTO_DESTROY  physicalCoresBuffer  =  ffStrbufCreate ();
482494    FF_STRBUF_AUTO_DESTROY  cpuMHz  =  ffStrbufCreate ();
483495    FF_STRBUF_AUTO_DESTROY  cpuIsa  =  ffStrbufCreate ();
484496    FF_STRBUF_AUTO_DESTROY  cpuUarch  =  ffStrbufCreate ();
485497    FF_STRBUF_AUTO_DESTROY  cpuImplementerStr  =  ffStrbufCreate ();
486498
487-     const  char *  error  =  parseCpuInfo (cpuinfo , cpu ,  & cpuPhysicalId , & physicalCoresBuffer , & cpuMHz , & cpuIsa , & cpuUarch , & cpuImplementerStr );
499+     const  char *  error  =  parseCpuInfo (& cpuinfo , cpu , & physicalCoresBuffer , & cpuMHz , & cpuIsa , & cpuUarch , & cpuImplementerStr );
488500    if  (error ) return  error ;
489501
490502    cpu -> coresLogical  =  (uint16_t ) get_nprocs_conf ();
491503    cpu -> coresOnline  =  (uint16_t ) get_nprocs ();
492504    cpu -> coresPhysical  =  (uint16_t ) ffStrbufToUInt (& physicalCoresBuffer , cpu -> coresLogical );
493-     cpu -> cpuCount  =  ( uint16_t )  ffStrbufToUInt ( & cpuPhysicalId ,  1 )  + 1 ;  //Assuming at least 1 CPU is present otherwise we wouldn't get this far 
505+     cpu -> cpuCount  =  getCPUCount ( & cpuinfo ); 
494506
495507    // Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252 
496508    ffCPUDetectSpeedByCpuid (cpu );
@@ -525,7 +537,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
525537    #endif 
526538
527539    if  (cpu -> name .length  ==  0 )
528-         detectArmName (cpuinfo , cpu , cpuImplementer );
540+         detectArmName (& cpuinfo , cpu , cpuImplementer );
529541    #endif 
530542
531543    return  NULL ;
0 commit comments