Index: trunk/src/ht_element.c =================================================================== --- trunk/src/ht_element.c (revision 5114) +++ trunk/src/ht_element.c (revision 5115) @@ -9,209 +9,3 @@ #warning TODO: move these in the big split -/* compare two strings and return 0 if they are equal. NULL == NULL means equal. */ -static int pcb_neqs(const char *s1, const char *s2) -{ - if ((s1 == NULL) && (s2 == NULL)) return 0; - if ((s1 == NULL) || (s2 == NULL)) return 1; - return strcmp(s1, s2) != 0; -} - -/* compare two fields and return 0 if they are equal */ -#define pcb_field_neq(s1, s2, f) ((s1)->f != (s2)->f) - -#define pcb_element_offs(e,ef, s,sf) ((e == NULL) ? (s)->sf : ((s)->sf) - ((e)->ef)) -#define pcb_element_neq_offsx(e1, x1, e2, x2, f) (pcb_element_offs(e1, MarkX, x1, f) != pcb_element_offs(e2, MarkX, x2, f)) -#define pcb_element_neq_offsy(e1, y1, e2, y2, f) (pcb_element_offs(e1, MarkY, y1, f) != pcb_element_offs(e2, MarkY, y2, f)) - -static inline unsigned h_coord(pcb_coord_t c) -{ - return murmurhash(&(c), sizeof(pcb_coord_t)); -} - -#define h_coordox(e, c) ((e) == NULL ? h_coord(c) : h_coord(c - e->MarkX)) -#define h_coordoy(e, c) ((e) == NULL ? h_coord(c) : h_coord(c - e->MarkY)) - -#define h_str(s) ((s) == NULL ? 0 : strhash(s)) - -int pcb_pin_eq(const pcb_element_t *e1, const pcb_pin_t *p1, const pcb_element_t *e2, const pcb_pin_t *p2) -{ - if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; - if (pcb_field_neq(p1, p2, Mask) || pcb_field_neq(p1, p2, DrillingHole)) return 0; - if (pcb_element_neq_offsx(e1, p1, e2, p2, X) || pcb_element_neq_offsy(e1, p1, e2, p2, Y)) return 0; - if (pcb_neqs(p1->Name, p2->Name)) return 0; - if (pcb_neqs(p1->Number, p2->Number)) return 0; - return 1; -} - -unsigned int pcb_pin_hash(const pcb_element_t *e, const pcb_pin_t *p) -{ - return - h_coord(p->Thickness) ^ h_coord(p->Clearance) ^ - h_coord(p->Mask) ^ h_coord(p->DrillingHole) ^ - h_coordox(e, p->X) ^ h_coordoy(e, p->Y) ^ - h_str(p->Name) ^ h_str(p->Number); -} - -int pcb_pad_eq(const pcb_element_t *e1, const pcb_pad_t *p1, const pcb_element_t *e2, const pcb_pad_t *p2) -{ - if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; - if (pcb_element_neq_offsx(e1, p1, e2, p2, Point1.X) || pcb_element_neq_offsy(e1, p1, e2, p2, Point1.Y)) return 0; - if (pcb_element_neq_offsx(e1, p1, e2, p2, Point2.X) || pcb_element_neq_offsy(e1, p1, e2, p2, Point2.Y)) return 0; - if (pcb_field_neq(p1, p2, Mask)) return 0; - if (pcb_neqs(p1->Name, p2->Name)) return 0; - if (pcb_neqs(p1->Number, p2->Number)) return 0; - return 1; -} - -unsigned int pcb_pad_hash(const pcb_element_t *e, const pcb_pad_t *p) -{ - return - h_coord(p->Thickness) ^ h_coord(p->Clearance) ^ - h_coordox(e, p->Point1.X) ^ h_coordoy(e, p->Point1.Y) ^ - h_coordox(e, p->Point2.X) ^ h_coordoy(e, p->Point2.Y) ^ - h_coord(p->Mask) ^ - h_str(p->Name) ^ h_str(p->Number); -} - - -int pcb_line_eq(const pcb_element_t *e1, const pcb_line_t *l1, const pcb_element_t *e2, const pcb_line_t *l2) -{ - if (pcb_field_neq(l1, l2, Thickness) || pcb_field_neq(l1, l2, Clearance)) return 0; - if (pcb_element_neq_offsx(e1, l1, e2, l2, Point1.X) || pcb_element_neq_offsy(e1, l1, e2, l2, Point1.Y)) return 0; - if (pcb_element_neq_offsx(e1, l1, e2, l2, Point2.X) || pcb_element_neq_offsy(e1, l1, e2, l2, Point2.Y)) return 0; - if (pcb_neqs(l1->Number, l2->Number)) return 0; - return 1; -} - - -unsigned int pcb_line_hash(const pcb_element_t *e, const pcb_line_t *l) -{ - return - h_coord(l->Thickness) ^ h_coord(l->Clearance) ^ - h_coordox(e, l->Point1.X) ^ h_coordoy(e, l->Point1.Y) ^ - h_coordox(e, l->Point2.X) ^ h_coordoy(e, l->Point2.Y) ^ - h_str(l->Number); -} - -int pcb_arc_eq(const pcb_element_t *e1, const pcb_arc_t *a1, const pcb_element_t *e2, const pcb_arc_t *a2) -{ - if (pcb_field_neq(a1, a2, Thickness) || pcb_field_neq(a1, a2, Clearance)) return 0; - if (pcb_field_neq(a1, a2, Width) || pcb_field_neq(a1, a2, Height)) return 0; - if (pcb_element_neq_offsx(e1, a1, e2, a2, X) || pcb_element_neq_offsy(e1, a1, e2, a2, Y)) return 0; - if (pcb_field_neq(a1, a2, StartAngle) || pcb_field_neq(a1, a2, Delta)) return 0; - - return 1; -} - -unsigned int pcb_arc_hash(const pcb_element_t *e, const pcb_arc_t *a) -{ - return - h_coord(a->Thickness) ^ h_coord(a->Clearance) ^ - h_coord(a->Width) ^ h_coord(a->Height) ^ - h_coordox(e, a->X) ^ h_coordoy(e, a->Y) ^ - h_coord(a->StartAngle) ^ h_coord(a->Delta); -} - -#undef h_coord -#undef neq - -unsigned int pcb_element_hash(const pcb_element_t *e) -{ - unsigned int val = 0; - gdl_iterator_t it; - - { - pcb_pin_t *p; - pinlist_foreach(&e->Pin, &it, p) { - val ^= pcb_pin_hash(e, p); - } - } - - { - pcb_pad_t *p; - padlist_foreach(&e->Pad, &it, p) { - val ^= pcb_pad_hash(e, p); - } - } - - { - pcb_line_t *l; - linelist_foreach(&e->Line, &it, l) { - val ^= pcb_line_hash(e, l); - } - } - - { - pcb_arc_t *a; - linelist_foreach(&e->Arc, &it, a) { - val ^= pcb_arc_hash(e, a); - } - } - - return val; -} - -int pcb_element_eq(const pcb_element_t *e1, const pcb_element_t *e2) -{ - /* Require the same objects in the same order - bail out at the first mismatch */ - - { - pcb_pin_t *p1, *p2; - p1 = pinlist_first((pinlist_t *)&e1->Pin); - p2 = pinlist_first((pinlist_t *)&e2->Pin); - for(;;) { - if ((p1 == NULL) && (p2 == NULL)) - break; - if (!pcb_pin_eq(e1, p1, e2, p2)) - return 0; - p1 = pinlist_next(p1); - p2 = pinlist_next(p2); - } - } - - { - pcb_pad_t *p1, *p2; - p1 = padlist_first((padlist_t *)&e1->Pad); - p2 = padlist_first((padlist_t *)&e2->Pad); - for(;;) { - if ((p1 == NULL) && (p2 == NULL)) - break; - if (!pcb_pad_eq(e1, p1, e2, p2)) - return 0; - p1 = padlist_next(p1); - p2 = padlist_next(p2); - } - } - - { - pcb_line_t *l1, *l2; - l1 = linelist_first((linelist_t *)&e1->Line); - l2 = linelist_first((linelist_t *)&e2->Line); - for(;;) { - if ((l1 == NULL) && (l2 == NULL)) - break; - if (!pcb_line_eq(e1, l1, e2, l2)) - return 0; - l1 = linelist_next(l1); - l2 = linelist_next(l2); - } - } - - { - pcb_arc_t *a1, *a2; - a1 = arclist_first((arclist_t *)&e1->Arc); - a2 = arclist_first((arclist_t *)&e2->Arc); - for(;;) { - if ((a1 == NULL) && (a2 == NULL)) - break; - if (!pcb_arc_eq(e1, a1, e2, a2)) - return 0; - a1 = arclist_next(a1); - a2 = arclist_next(a2); - } - } - - return 1; -} - Index: trunk/src/obj_arc.c =================================================================== --- trunk/src/obj_arc.c (revision 5114) +++ trunk/src/obj_arc.c (revision 5115) @@ -218,6 +218,25 @@ } +int pcb_arc_eq(const pcb_element_t *e1, const pcb_arc_t *a1, const pcb_element_t *e2, const pcb_arc_t *a2) +{ + if (pcb_field_neq(a1, a2, Thickness) || pcb_field_neq(a1, a2, Clearance)) return 0; + if (pcb_field_neq(a1, a2, Width) || pcb_field_neq(a1, a2, Height)) return 0; + if (pcb_element_neq_offsx(e1, a1, e2, a2, X) || pcb_element_neq_offsy(e1, a1, e2, a2, Y)) return 0; + if (pcb_field_neq(a1, a2, StartAngle) || pcb_field_neq(a1, a2, Delta)) return 0; + + return 1; +} + +unsigned int pcb_arc_hash(const pcb_element_t *e, const pcb_arc_t *a) +{ + return + h_coord(a->Thickness) ^ h_coord(a->Clearance) ^ + h_coord(a->Width) ^ h_coord(a->Height) ^ + h_coordox(e, a->X) ^ h_coordoy(e, a->Y) ^ + h_coord(a->StartAngle) ^ h_coord(a->Delta); +} + /***** operations *****/ /* copies an arc to buffer */ Index: trunk/src/obj_arc.h =================================================================== --- trunk/src/obj_arc.h (revision 5114) +++ trunk/src/obj_arc.h (revision 5115) @@ -58,7 +58,11 @@ void pcb_arc_rotate90(pcb_arc_t *Arc, pcb_coord_t X, pcb_coord_t Y, unsigned Number); void pcb_arc_rotate(pcb_layer_t *layer, pcb_arc_t *arc, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina, pcb_angle_t angle); +/*** hash ***/ +int pcb_arc_eq(const pcb_element_t *e1, const pcb_arc_t *a1, const pcb_element_t *e2, const pcb_arc_t *a2); +unsigned int pcb_arc_hash(const pcb_element_t *e, const pcb_arc_t *a); + pcb_box_t *pcb_arc_get_ends(pcb_arc_t *Arc); void pcb_arc_set_angles(pcb_layer_t *Layer, pcb_arc_t *a, pcb_angle_t new_sa, pcb_angle_t new_da); void pcb_arc_set_radii(pcb_layer_t *Layer, pcb_arc_t *a, pcb_coord_t new_width, pcb_coord_t new_height); Index: trunk/src/obj_common.h =================================================================== --- trunk/src/obj_common.h (revision 5114) +++ trunk/src/obj_common.h (revision 5115) @@ -27,7 +27,9 @@ #ifndef PCB_OBJ_COMMON_H #define PCB_OBJ_COMMON_H +#include #include +#include #include "flag.h" #include "attrib.h" #include "global_typedefs.h" @@ -101,4 +103,32 @@ PCB_ANYLINEFIELDS; } pcb_any_line_t; +/*** Functions and macros used for hashing ***/ + +/* compare two strings and return 0 if they are equal. NULL == NULL means equal. */ +static inline PCB_FUNC_UNUSED int pcb_neqs(const char *s1, const char *s2) +{ + if ((s1 == NULL) && (s2 == NULL)) return 0; + if ((s1 == NULL) || (s2 == NULL)) return 1; + return strcmp(s1, s2) != 0; +} + +static inline PCB_FUNC_UNUSED unsigned h_coord(pcb_coord_t c) +{ + return murmurhash(&(c), sizeof(pcb_coord_t)); +} + + +/* compare two fields and return 0 if they are equal */ +#define pcb_field_neq(s1, s2, f) ((s1)->f != (s2)->f) + +#define h_coordox(e, c) ((e) == NULL ? h_coord(c) : h_coord(c - e->MarkX)) +#define h_coordoy(e, c) ((e) == NULL ? h_coord(c) : h_coord(c - e->MarkY)) + +#define h_str(s) ((s) == NULL ? 0 : strhash(s)) + +#define pcb_element_offs(e,ef, s,sf) ((e == NULL) ? (s)->sf : ((s)->sf) - ((e)->ef)) +#define pcb_element_neq_offsx(e1, x1, e2, x2, f) (pcb_element_offs(e1, MarkX, x1, f) != pcb_element_offs(e2, MarkX, x2, f)) +#define pcb_element_neq_offsy(e1, y1, e2, y2, f) (pcb_element_offs(e1, MarkY, y1, f) != pcb_element_offs(e2, MarkY, y2, f)) + #endif Index: trunk/src/obj_elem.c =================================================================== --- trunk/src/obj_elem.c (revision 5114) +++ trunk/src/obj_elem.c (revision 5115) @@ -1107,7 +1107,107 @@ pcb_poly_clear_from_poly(Data, PCB_TYPE_ELEMENT, Element, Element); } +unsigned int pcb_element_hash(const pcb_element_t *e) +{ + unsigned int val = 0; + gdl_iterator_t it; + { + pcb_pin_t *p; + pinlist_foreach(&e->Pin, &it, p) { + val ^= pcb_pin_hash(e, p); + } + } + + { + pcb_pad_t *p; + padlist_foreach(&e->Pad, &it, p) { + val ^= pcb_pad_hash(e, p); + } + } + + { + pcb_line_t *l; + linelist_foreach(&e->Line, &it, l) { + val ^= pcb_line_hash(e, l); + } + } + + { + pcb_arc_t *a; + linelist_foreach(&e->Arc, &it, a) { + val ^= pcb_arc_hash(e, a); + } + } + + return val; +} + +int pcb_element_eq(const pcb_element_t *e1, const pcb_element_t *e2) +{ + /* Require the same objects in the same order - bail out at the first mismatch */ + + { + pcb_pin_t *p1, *p2; + p1 = pinlist_first((pinlist_t *)&e1->Pin); + p2 = pinlist_first((pinlist_t *)&e2->Pin); + for(;;) { + if ((p1 == NULL) && (p2 == NULL)) + break; + if (!pcb_pin_eq(e1, p1, e2, p2)) + return 0; + p1 = pinlist_next(p1); + p2 = pinlist_next(p2); + } + } + + { + pcb_pad_t *p1, *p2; + p1 = padlist_first((padlist_t *)&e1->Pad); + p2 = padlist_first((padlist_t *)&e2->Pad); + for(;;) { + if ((p1 == NULL) && (p2 == NULL)) + break; + if (!pcb_pad_eq(e1, p1, e2, p2)) + return 0; + p1 = padlist_next(p1); + p2 = padlist_next(p2); + } + } + + { + pcb_line_t *l1, *l2; + l1 = linelist_first((linelist_t *)&e1->Line); + l2 = linelist_first((linelist_t *)&e2->Line); + for(;;) { + if ((l1 == NULL) && (l2 == NULL)) + break; + if (!pcb_line_eq(e1, l1, e2, l2)) + return 0; + l1 = linelist_next(l1); + l2 = linelist_next(l2); + } + } + + { + pcb_arc_t *a1, *a2; + a1 = arclist_first((arclist_t *)&e1->Arc); + a2 = arclist_first((arclist_t *)&e2->Arc); + for(;;) { + if ((a1 == NULL) && (a2 == NULL)) + break; + if (!pcb_arc_eq(e1, a1, e2, a2)) + return 0; + a1 = arclist_next(a1); + a2 = arclist_next(a2); + } + } + + return 1; +} + + + /*** ops ***/ /* copies a element to buffer */ void *AddElementToBuffer(pcb_opctx_t *ctx, pcb_element_t *Element) Index: trunk/src/obj_elem.h =================================================================== --- trunk/src/obj_elem.h (revision 5114) +++ trunk/src/obj_elem.h (revision 5115) @@ -72,7 +72,11 @@ comparing two similar footprints. */ int pcb_element_get_orientation(pcb_element_t * e); +/* hash */ +unsigned int pcb_element_hash(const pcb_element_t *e); +int pcb_element_eq(const pcb_element_t *e1, const pcb_element_t *e2); + pcb_bool pcb_element_load_to_buffer(pcb_buffer_t *Buffer, const char *Name); int pcb_element_load_footprint_by_name(pcb_buffer_t *Buffer, const char *Footprint); pcb_bool pcb_element_smash_buffer(pcb_buffer_t *Buffer); Index: trunk/src/obj_line.c =================================================================== --- trunk/src/obj_line.c (revision 5114) +++ trunk/src/obj_line.c (revision 5115) @@ -238,9 +238,28 @@ pcb_set_point_bounding_box(&Line->Point2); } +int pcb_line_eq(const pcb_element_t *e1, const pcb_line_t *l1, const pcb_element_t *e2, const pcb_line_t *l2) +{ + if (pcb_field_neq(l1, l2, Thickness) || pcb_field_neq(l1, l2, Clearance)) return 0; + if (pcb_element_neq_offsx(e1, l1, e2, l2, Point1.X) || pcb_element_neq_offsy(e1, l1, e2, l2, Point1.Y)) return 0; + if (pcb_element_neq_offsx(e1, l1, e2, l2, Point2.X) || pcb_element_neq_offsy(e1, l1, e2, l2, Point2.Y)) return 0; + if (pcb_neqs(l1->Number, l2->Number)) return 0; + return 1; +} +unsigned int pcb_line_hash(const pcb_element_t *e, const pcb_line_t *l) +{ + return + h_coord(l->Thickness) ^ h_coord(l->Clearance) ^ + h_coordox(e, l->Point1.X) ^ h_coordoy(e, l->Point1.Y) ^ + h_coordox(e, l->Point2.X) ^ h_coordoy(e, l->Point2.Y) ^ + h_str(l->Number); +} + + + /*** ops ***/ /* copies a line to buffer */ Index: trunk/src/obj_line.h =================================================================== --- trunk/src/obj_line.h (revision 5114) +++ trunk/src/obj_line.h (revision 5115) @@ -61,6 +61,11 @@ void pcb_line_rotate90(pcb_line_t *Line, pcb_coord_t X, pcb_coord_t Y, unsigned Number); void pcb_line_rotate(pcb_layer_t *layer, pcb_line_t *line, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina); +/* hash */ +int pcb_line_eq(const pcb_element_t *e1, const pcb_line_t *l1, const pcb_element_t *e2, const pcb_line_t *l2); +unsigned int pcb_line_hash(const pcb_element_t *e, const pcb_line_t *l); + + /*** DRC enforcement (obj_line_drcenf.c) ***/ void pcb_line_adjust_attached(void); void pcb_line_adjust_attached_2lines(pcb_bool); Index: trunk/src/obj_pad.c =================================================================== --- trunk/src/obj_pad.c (revision 5114) +++ trunk/src/obj_pad.c (revision 5115) @@ -152,6 +152,28 @@ return (pcb_true); } +int pcb_pad_eq(const pcb_element_t *e1, const pcb_pad_t *p1, const pcb_element_t *e2, const pcb_pad_t *p2) +{ + if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; + if (pcb_element_neq_offsx(e1, p1, e2, p2, Point1.X) || pcb_element_neq_offsy(e1, p1, e2, p2, Point1.Y)) return 0; + if (pcb_element_neq_offsx(e1, p1, e2, p2, Point2.X) || pcb_element_neq_offsy(e1, p1, e2, p2, Point2.Y)) return 0; + if (pcb_field_neq(p1, p2, Mask)) return 0; + if (pcb_neqs(p1->Name, p2->Name)) return 0; + if (pcb_neqs(p1->Number, p2->Number)) return 0; + return 1; +} + +unsigned int pcb_pad_hash(const pcb_element_t *e, const pcb_pad_t *p) +{ + return + h_coord(p->Thickness) ^ h_coord(p->Clearance) ^ + h_coordox(e, p->Point1.X) ^ h_coordoy(e, p->Point1.Y) ^ + h_coordox(e, p->Point2.X) ^ h_coordoy(e, p->Point2.Y) ^ + h_coord(p->Mask) ^ + h_str(p->Name) ^ h_str(p->Number); +} + + /*** ops ***/ /* changes the size of a pad */ Index: trunk/src/obj_pad.h =================================================================== --- trunk/src/obj_pad.h (revision 5114) +++ trunk/src/obj_pad.h (revision 5115) @@ -49,7 +49,11 @@ pcb_bool pcb_pad_change_paste(pcb_pad_t *Pad); +/* hash */ +int pcb_pad_eq(const pcb_element_t *e1, const pcb_pad_t *p1, const pcb_element_t *e2, const pcb_pad_t *p2); +unsigned int pcb_pad_hash(const pcb_element_t *e, const pcb_pad_t *p); + /* Rather than move the line bounding box, we set it so the point bounding * boxes are updated too. */ Index: trunk/src/obj_pinvia.c =================================================================== --- trunk/src/obj_pinvia.c (revision 5114) +++ trunk/src/obj_pinvia.c (revision 5115) @@ -239,7 +239,26 @@ } +int pcb_pin_eq(const pcb_element_t *e1, const pcb_pin_t *p1, const pcb_element_t *e2, const pcb_pin_t *p2) +{ + if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; + if (pcb_field_neq(p1, p2, Mask) || pcb_field_neq(p1, p2, DrillingHole)) return 0; + if (pcb_element_neq_offsx(e1, p1, e2, p2, X) || pcb_element_neq_offsy(e1, p1, e2, p2, Y)) return 0; + if (pcb_neqs(p1->Name, p2->Name)) return 0; + if (pcb_neqs(p1->Number, p2->Number)) return 0; + return 1; +} +unsigned int pcb_pin_hash(const pcb_element_t *e, const pcb_pin_t *p) +{ + return + h_coord(p->Thickness) ^ h_coord(p->Clearance) ^ + h_coord(p->Mask) ^ h_coord(p->DrillingHole) ^ + h_coordox(e, p->X) ^ h_coordoy(e, p->Y) ^ + h_str(p->Name) ^ h_str(p->Number); +} + + /*** ops ***/ /* copies a via to paste buffer */ void *AddViaToBuffer(pcb_opctx_t *ctx, pcb_pin_t *Via) Index: trunk/src/obj_pinvia.h =================================================================== --- trunk/src/obj_pinvia.h (revision 5114) +++ trunk/src/obj_pinvia.h (revision 5115) @@ -54,6 +54,9 @@ void pcb_via_rotate(pcb_data_t *Data, pcb_pin_t *Via, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina); +/* hash */ +int pcb_pin_eq(const pcb_element_t *e1, const pcb_pin_t *p1, const pcb_element_t *e2, const pcb_pin_t *p2); +unsigned int pcb_pin_hash(const pcb_element_t *e, const pcb_pin_t *p); pcb_bool pcb_pin_change_hole(pcb_pin_t *Via);