UInt completion_rnam ( Char * name, UInt len ) { const Char * curr; const Char * next; UInt i, k; const UInt countRNam = LEN_PLIST(NamesRNam); next = 0; for ( i = 1; i <= countRNam; i++ ) { curr = CONST_CSTR_STRING( NAME_RNAM( i ) ); for ( k = 0; name[k] != 0 && curr[k] == name[k]; k++ ) ; if ( k < len || curr[k] <= name[k] ) continue; if ( next != 0 ) { for ( k = 0; curr[k] != '\0' && curr[k] == next[k]; k++ ) ; if ( k < len || next[k] < curr[k] ) continue; } next = curr; } if ( next != 0 ) { for ( k = 0; next[k] != '\0'; k++ ) name[k] = next[k]; name[k] = '\0'; } return next != 0; }
UInt completion_rnam ( Char * name, UInt len ) { Char * curr; Char * next; UInt i, k; next = 0; for ( i = 1; i <= CountRNam; i++ ) { curr = NAME_RNAM( i ); for ( k = 0; name[k] != 0 && curr[k] == name[k]; k++ ) ; if ( k < len || curr[k] <= name[k] ) continue; if ( next != 0 ) { for ( k = 0; curr[k] != '\0' && curr[k] == next[k]; k++ ) ; if ( k < len || next[k] < curr[k] ) continue; } next = curr; } if ( next != 0 ) { for ( k = 0; next[k] != '\0'; k++ ) name[k] = next[k]; name[k] = '\0'; } return next != 0; }
/**************************************************************************** ** *F iscomplete( <name>, <len> ) . . . . . . . . find the completions of name *F completion( <name>, <len> ) . . . . . . . . find the completions of name */ UInt iscomplete_rnam ( Char * name, UInt len ) { Char * curr; UInt i, k; for ( i = 1; i <= CountRNam; i++ ) { curr = NAME_RNAM( i ); for ( k = 0; name[k] != 0 && curr[k] == name[k]; k++ ) ; if ( k == len && curr[k] == '\0' ) return 1; } return 0; }
/**************************************************************************** ** *F iscomplete( <name>, <len> ) . . . . . . . . find the completions of name *F completion( <name>, <len> ) . . . . . . . . find the completions of name */ UInt iscomplete_rnam ( Char * name, UInt len ) { const Char * curr; UInt i, k; const UInt countRNam = LEN_PLIST(NamesRNam); for ( i = 1; i <= countRNam; i++ ) { curr = CONST_CSTR_STRING( NAME_RNAM( i ) ); for ( k = 0; name[k] != 0 && curr[k] == name[k]; k++ ) ; if ( k == len && curr[k] == '\0' ) return 1; } return 0; }
static Obj FuncALL_RNAMES(Obj self) { Obj copy, s; UInt i; Obj name; const UInt countRNam = LEN_PLIST(NamesRNam); copy = NEW_PLIST_IMM( T_PLIST, countRNam ); for ( i = 1; i <= countRNam; i++ ) { name = NAME_RNAM( i ); s = CopyToStringRep(name); SET_ELM_PLIST( copy, i, s ); } SET_LEN_PLIST( copy, countRNam ); return copy; }
Obj FuncALL_RNAMES ( Obj self ) { Obj copy, s; UInt i; Char* name; copy = NEW_PLIST( T_PLIST+IMMUTABLE, CountRNam ); for ( i = 1; i <= CountRNam; i++ ) { name = NAME_RNAM( i ); C_NEW_STRING_DYN(s, name); SET_ELM_PLIST( copy, i, s ); } SET_LEN_PLIST( copy, CountRNam ); return copy; }
/**************************************************************************** ** *F FuncNameRNam(<self>,<rnam>) . . . . convert a record name to a string ** ** 'FuncNameRNam' implements the internal function 'NameRName'. ** ** 'NameRName( <rnam> )' ** ** 'NameRName' returns the string corresponding to the record name <rnam>. */ static Obj FuncNameRNam(Obj self, Obj rnam) { Obj name; Obj oname; const UInt countRNam = LEN_PLIST(NamesRNam); while ( ! IS_INTOBJ(rnam) || INT_INTOBJ(rnam) <= 0 || countRNam < INT_INTOBJ(rnam) ) { rnam = ErrorReturnObj( "NameRName: <rnam> must be a record name (not a %s)", (Int)TNAM_OBJ(rnam), 0L, "you can replace <rnam> via 'return <rnam>;'" ); } oname = NAME_RNAM( INT_INTOBJ(rnam) ); name = CopyToStringRep(oname); return name; }
Obj NameRNamHandler ( Obj self, Obj rnam ) { Obj name; Char *cname; while ( ! IS_INTOBJ(rnam) || INT_INTOBJ(rnam) <= 0 || CountRNam < INT_INTOBJ(rnam) ) { rnam = ErrorReturnObj( "NameRName: <rnam> must be a record name (not a %s)", (Int)TNAM_OBJ(rnam), 0L, "you can replace <rnam> via 'return <rnam>;'" ); } cname = NAME_RNAM( INT_INTOBJ(rnam) ); C_NEW_STRING_DYN( name, cname); return name; }
UInt RNamNameWithLen(const Char * name, UInt len) { Obj rnam; /* record name (as imm intobj) */ UInt pos; /* hash position */ Char namx [1024]; /* temporary copy of <name> */ Obj string; /* temporary string object <name> */ Obj table; /* temporary copy of <HashRNam> */ Obj rnam2; /* one element of <table> */ UInt i; /* loop variable */ UInt sizeRNam; if (len > 1023) { // Note: We can't pass 'name' here, as it might get moved by garbage collection ErrorQuit("Record names must consist of at most 1023 characters", 0, 0); } /* start looking in the table at the following hash position */ const UInt hash = HashString( name, len ); #ifdef HPCGAP HPC_LockNames(0); /* try a read lock first */ #endif /* look through the table until we find a free slot or the global */ sizeRNam = LEN_PLIST(HashRNam); pos = (hash % sizeRNam) + 1; while ( (rnam = ELM_PLIST( HashRNam, pos )) != 0 && !EqString( NAME_RNAM( INT_INTOBJ(rnam) ), name, len ) ) { pos = (pos % sizeRNam) + 1; } if (rnam != 0) { #ifdef HPCGAP HPC_UnlockNames(); #endif return INT_INTOBJ(rnam); } #ifdef HPCGAP if (!PreThreadCreation) { HPC_UnlockNames(); /* switch to a write lock */ HPC_LockNames(1); /* look through the table until we find a free slot or the global */ sizeRNam = LEN_PLIST(HashRNam); pos = (hash % sizeRNam) + 1; while ( (rnam = ELM_PLIST( HashRNam, pos )) != 0 && !EqString( NAME_RNAM( INT_INTOBJ(rnam) ), name, len ) ) { pos = (pos % sizeRNam) + 1; } } if (rnam != 0) { HPC_UnlockNames(); return INT_INTOBJ(rnam); } #endif /* if we did not find the global variable, make a new one and enter it */ /* (copy the name first, to avoid a stale pointer in case of a GC) */ memcpy( namx, name, len ); namx[len] = 0; string = MakeImmString(namx); const UInt countRNam = PushPlist(NamesRNam, string); rnam = INTOBJ_INT(countRNam); SET_ELM_PLIST( HashRNam, pos, rnam ); /* if the table is too crowded, make a larger one, rehash the names */ if ( sizeRNam < 3 * countRNam / 2 ) { table = HashRNam; sizeRNam = 2 * sizeRNam + 1; HashRNam = NEW_PLIST( T_PLIST, sizeRNam ); SET_LEN_PLIST( HashRNam, sizeRNam ); #ifdef HPCGAP /* The list is briefly non-public, but this is safe, because * the mutex protects it from being accessed by other threads. */ MakeBagPublic(HashRNam); #endif for ( i = 1; i <= (sizeRNam-1)/2; i++ ) { rnam2 = ELM_PLIST( table, i ); if ( rnam2 == 0 ) continue; string = NAME_RNAM( INT_INTOBJ(rnam2) ); pos = HashString( CONST_CSTR_STRING( string ), GET_LEN_STRING( string) ); pos = (pos % sizeRNam) + 1; while ( ELM_PLIST( HashRNam, pos ) != 0 ) { pos = (pos % sizeRNam) + 1; } SET_ELM_PLIST( HashRNam, pos, rnam2 ); } } #ifdef HPCGAP HPC_UnlockNames(); #endif /* return the record name */ return INT_INTOBJ(rnam); }
UInt RNamName ( const Char * name ) { Obj rnam; /* record name (as imm intobj) */ UInt pos; /* hash position */ UInt len; /* length of name */ Char namx [1024]; /* temporary copy of <name> */ Obj string; /* temporary string object <name> */ Obj table; /* temporary copy of <HashRNam> */ Obj rnam2; /* one element of <table> */ const Char * p; /* loop variable */ UInt i; /* loop variable */ /* start looking in the table at the following hash position */ pos = 0; len = 0; for ( p = name; *p != '\0'; p++ ) { pos = 65599 * pos + *p; len++; } pos = (pos % SizeRNam) + 1; if(len >= 1023) { // Note: We can't pass 'name' here, as it might get moved by garbage collection ErrorQuit("Record names must consist of less than 1023 characters", 0, 0); } /* look through the table until we find a free slot or the global */ while ( (rnam = ELM_PLIST( HashRNam, pos )) != 0 && strncmp( NAME_RNAM( INT_INTOBJ(rnam) ), name, 1023 ) ) { pos = (pos % SizeRNam) + 1; } /* if we did not find the global variable, make a new one and enter it */ /* (copy the name first, to avoid a stale pointer in case of a GC) */ if ( rnam == 0 ) { CountRNam++; rnam = INTOBJ_INT(CountRNam); SET_ELM_PLIST( HashRNam, pos, rnam ); strlcpy( namx, name, sizeof(namx) ); C_NEW_STRING_DYN(string, namx); GROW_PLIST( NamesRNam, CountRNam ); SET_LEN_PLIST( NamesRNam, CountRNam ); SET_ELM_PLIST( NamesRNam, CountRNam, string ); CHANGED_BAG( NamesRNam ); } /* if the table is too crowed, make a larger one, rehash the names */ if ( SizeRNam < 3 * CountRNam / 2 ) { table = HashRNam; SizeRNam = 2 * SizeRNam + 1; HashRNam = NEW_PLIST( T_PLIST, SizeRNam ); SET_LEN_PLIST( HashRNam, SizeRNam ); for ( i = 1; i <= (SizeRNam-1)/2; i++ ) { rnam2 = ELM_PLIST( table, i ); if ( rnam2 == 0 ) continue; pos = 0; for ( p = NAME_RNAM( INT_INTOBJ(rnam2) ); *p != '\0'; p++ ) { pos = 65599 * pos + *p; } pos = (pos % SizeRNam) + 1; while ( ELM_PLIST( HashRNam, pos ) != 0 ) { pos = (pos % SizeRNam) + 1; } SET_ELM_PLIST( HashRNam, pos, rnam2 ); } } /* return the record name */ return INT_INTOBJ(rnam); }